From 8fab074d059363063fff9d32586596d4b7e4921f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20E=2E=20Garcia=20Maci=C3=B1eiras?= <68995937+jemacineiras@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:05:23 +0100 Subject: [PATCH] 309 fail to execute a file (#310) * 309 Fix wrong schema generation --- multiapi-engine/pom.xml | 2 +- .../plugin/asyncapi/util/MapperUtil.java | 10 ++- .../plugin/openapi/OpenApiGenerator.java | 49 +++++++------- .../plugin/openapi/model/TypeConstants.java | 15 +++++ .../openapi/template/TemplateFactory.java | 39 ++++++----- .../openapi/OpenApiGeneratorFixtures.java | 45 +++++++++++-- .../plugin/openapi/OpenApiGeneratorTest.java | 2 + .../testCreateBasicDTO/api-test.yml | 67 +++++++++++++++++++ .../testCreateBasicDTO/assets/TestApi.java | 46 +++++++++++++ .../assets/model/AddressDTO.java | 33 +++++++++ .../assets/model/TestDTO.java | 39 +++++++++++ scs-multiapi-gradle-plugin/build.gradle | 6 +- scs-multiapi-maven-plugin/pom.xml | 4 +- 13 files changed, 300 insertions(+), 57 deletions(-) create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/api-test.yml create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/TestApi.java create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/model/AddressDTO.java create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/model/TestDTO.java diff --git a/multiapi-engine/pom.xml b/multiapi-engine/pom.xml index 4a609a67..ebdfadde 100644 --- a/multiapi-engine/pom.xml +++ b/multiapi-engine/pom.xml @@ -4,7 +4,7 @@ com.sngular multiapi-engine - 5.3.0 + 5.3.1 jar diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/asyncapi/util/MapperUtil.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/asyncapi/util/MapperUtil.java index 6426b3bc..febddc46 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/asyncapi/util/MapperUtil.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/asyncapi/util/MapperUtil.java @@ -87,12 +87,10 @@ public static String formatTypeOfString(final String format, final TimeType useT String type = "String"; if (format != null) { if (DATE_TIME.equalsIgnoreCase(format)) { - switch(useTimeType) { - case ZONED: - type = ZONED_DATE_TIME; - break; - default: - type = LOCAL_DATE_TIME; + if (Objects.requireNonNull(useTimeType) == TimeType.ZONED) { + type = ZONED_DATE_TIME; + } else { + type = LOCAL_DATE_TIME; } } else if (DATE.equalsIgnoreCase(format)) { diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/OpenApiGenerator.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/OpenApiGenerator.java index e15ef1fb..fcdd82fc 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/OpenApiGenerator.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/OpenApiGenerator.java @@ -6,6 +6,19 @@ package com.sngular.api.generator.plugin.openapi; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.regex.Pattern; + import com.fasterxml.jackson.databind.JsonNode; import com.sngular.api.generator.plugin.PluginConstants; import com.sngular.api.generator.plugin.common.tools.ApiTool; @@ -27,18 +40,6 @@ import com.sngular.api.generator.plugin.openapi.utils.MapperUtil; import com.sngular.api.generator.plugin.openapi.utils.OpenApiUtil; import freemarker.template.TemplateException; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.regex.Pattern; import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; @@ -302,17 +303,19 @@ private void processModels( final Map basicSchemaMap, final boolean overwrite) { final Map builtSchemasMap = new HashMap<>(); - basicSchemaMap.forEach( - (schemaName, basicSchema) -> - processModel( - specFile, - fileModelToSave, - modelPackage, - basicSchemaMap, - overwrite, - schemaName, - basicSchema, - builtSchemasMap)); + basicSchemaMap.forEach((schemaName, basicSchema) -> { + if (ApiTool.hasType(basicSchema)) { + if (validType(ApiTool.getType(basicSchema))) { + processModel(specFile, fileModelToSave, modelPackage, basicSchemaMap, overwrite, schemaName, basicSchema, builtSchemasMap); + } + } else { + processModel(specFile, fileModelToSave, modelPackage, basicSchemaMap, overwrite, schemaName, basicSchema, builtSchemasMap); + } + }); + } + + private boolean validType(final String type) { + return !TypeConstants.NO_PROCESS_TYPE.contains(type); } private void processModel( diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/TypeConstants.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/TypeConstants.java index 06abe68c..24ba8e09 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/TypeConstants.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/TypeConstants.java @@ -54,6 +54,21 @@ public final class TypeConstants { public static final Set NO_IMPORT_TYPE = Set.of(STRING, INTEGER, OBJECT); + public static final Set NO_PROCESS_TYPE = Set.of(NUMBER, + BOOLEAN, + BIG_DECIMAL, + INTEGER, + DOUBLE, + FLOAT, + LONG, + STRING, + ENUM, + LOCALDATE, + LOCALDATETIME, + ZONEDDATE, + ZONEDDATETIME, + OFFSETDATE, + OFFSETDATETIME); public static final Set ALL_TYPES = Set.of( NUMBER, BOOLEAN, diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/template/TemplateFactory.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/template/TemplateFactory.java index bec38b4b..30fde2b8 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/template/TemplateFactory.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/template/TemplateFactory.java @@ -6,16 +6,6 @@ package com.sngular.api.generator.plugin.openapi.template; -import com.sngular.api.generator.plugin.openapi.exception.OverwritingApiFilesException; -import com.sngular.api.generator.plugin.openapi.model.AuthObject; -import com.sngular.api.generator.plugin.openapi.model.PathObject; -import com.sngular.api.generator.plugin.openapi.model.SchemaFieldObject; -import com.sngular.api.generator.plugin.openapi.model.SchemaObject; -import com.sngular.api.generator.plugin.openapi.parameter.OpenAPISpecFile; -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateException; -import freemarker.template.TemplateExceptionHandler; import java.io.File; import java.io.FileWriter; import java.io.IOException; @@ -27,6 +17,17 @@ import java.util.Objects; import java.util.Set; +import com.sngular.api.generator.plugin.openapi.exception.OverwritingApiFilesException; +import com.sngular.api.generator.plugin.openapi.model.AuthObject; +import com.sngular.api.generator.plugin.openapi.model.PathObject; +import com.sngular.api.generator.plugin.openapi.model.SchemaFieldObject; +import com.sngular.api.generator.plugin.openapi.model.SchemaObject; +import com.sngular.api.generator.plugin.openapi.parameter.OpenAPISpecFile; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; + public class TemplateFactory { public static final String JAVA_EXTENSION = ".java"; @@ -105,7 +106,7 @@ public final void fillTemplateRestClient(final String filePathToSave) throws IOE } - public final void fillTemplateAuth(final String filePathToSave, final String authName) throws IOException, TemplateException { + public final void fillTemplateAuth(final String filePathToSave, final String authName) throws IOException { final File fileToSave = new File(filePathToSave); final var nameAuthClass = authName + JAVA_EXTENSION; final String pathToSaveMainClass = fileToSave.toPath().resolve(nameAuthClass).toString(); @@ -115,7 +116,7 @@ public final void fillTemplateAuth(final String filePathToSave, final String aut public final void fillTemplateCustom( final String filePathToSave, final String annotationFileName, final String validatorFileName, final String annotationTemplate, - final String validatorTemplate) throws IOException, TemplateException { + final String validatorTemplate) throws IOException { final File fileToSave = new File(filePathToSave); final Path pathToValidatorPackage = fileToSave.toPath().resolve("customvalidator"); pathToValidatorPackage.toFile().mkdirs(); @@ -157,18 +158,20 @@ public final void calculateJavaEEPackage(final Integer springBootVersion) { } } - private void writeTemplateToFile(final String templateName, final Map root, final String path) throws IOException, TemplateException { + private void writeTemplateToFile(final String templateName, final Map root, final String path) throws IOException { writeTemplateToFile(templateName, root, path, true); } - private void writeTemplateToFile(final String templateName, final Map root, final String path, final boolean checkOverwrite) throws IOException, - TemplateException { + private void writeTemplateToFile(final String templateName, final Map root, final String path, final boolean checkOverwrite) throws IOException { final Template template = cfg.getTemplate(templateName); if (!Files.exists(Path.of(path)) || checkOverwrite) { - final FileWriter writer = new FileWriter(path); - template.process(root, writer); - writer.close(); + try (FileWriter writer = new FileWriter(path)) { + template.process(root, writer); + } catch (IOException | TemplateException exception) { + final var schema = root.get("schema"); + throw new GeneratorTemplateException(String.format(" Error processing template %s with object %s", templateName, ((SchemaObject) schema).getClassName()), exception); + } } else { throw new OverwritingApiFilesException(); } diff --git a/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorFixtures.java b/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorFixtures.java index aa163ffa..a31f7447 100644 --- a/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorFixtures.java +++ b/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorFixtures.java @@ -8,15 +8,16 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.sngular.api.generator.plugin.openapi.model.TypeConstants.TimeType; -import com.sngular.api.generator.plugin.openapi.parameter.OpenAPISpecFile; -import com.sngular.api.generator.test.utils.TestUtils; import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.Collections; import java.util.List; import java.util.function.Function; + +import com.sngular.api.generator.plugin.openapi.model.TypeConstants.TimeType; +import com.sngular.api.generator.plugin.openapi.parameter.OpenAPISpecFile; +import com.sngular.api.generator.test.utils.TestUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -377,8 +378,20 @@ public final class OpenApiGeneratorFixtures { .build() ); + static final List TEST_CREATE_BASIC_DTO = List.of( + OpenAPISpecFile + .builder() + .filePath("openapigenerator/testCreateBasicDTO/api-test.yml") + .apiPackage("com.sngular.multifileplugin.testCreateBasicDTO") + .modelPackage("com.sngular.multifileplugin.testCreateBasicDTO.model") + .clientPackage("com.sngular.multifileplugin.testCreateBasicDTO.client") + .modelNameSuffix("DTO") + .useLombokModelAnnotation(true) + .build() + ); + static final List TEST_ISSUE_FAKER = List.of( - OpenAPISpecFile + OpenAPISpecFile .builder() .filePath("openapigenerator/testIssueFaker/api-test.yml") .apiPackage("com.sngular.multifileplugin.testissuefaker") @@ -1280,6 +1293,30 @@ static Function validateCreateDTO() { return (path) -> commonTest(path, expectedTestApiFile, expectedTestApiModelFiles, DEFAULT_TARGET_API, DEFAULT_MODEL_API, Collections.emptyList(), DEFAULT_EXCEPTION_API); } + static Function validateCreateBasicDTO() { + + final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testCreateBasicDTO"; + + final String DEFAULT_MODEL_API = "generated/com/sngular/multifileplugin/testCreateBasicDTO/model"; + + final String DEFAULT_EXCEPTION_API = "generated/com/sngular/multifileplugin/testCreateBasicDTO/model/exception"; + + final String COMMON_PATH = "openapigenerator/testCreateBasicDTO/"; + + final String ASSETS_PATH = COMMON_PATH + "assets/"; + + final List expectedTestApiFile = List.of( + ASSETS_PATH + "TestApi.java" + ); + + final List expectedTestApiModelFiles = List.of( + ASSETS_PATH + "model/AddressDTO.java", + ASSETS_PATH + "model/TestDTO.java" + ); + + return (path) -> commonTest(path, expectedTestApiFile, expectedTestApiModelFiles, DEFAULT_TARGET_API, DEFAULT_MODEL_API, Collections.emptyList(), DEFAULT_EXCEPTION_API); + } + static Function validateIssueFaker() { final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testissuefaker"; diff --git a/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorTest.java b/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorTest.java index b9781e6b..35e061dd 100644 --- a/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorTest.java +++ b/multiapi-engine/src/test/java/com/sngular/api/generator/plugin/openapi/OpenApiGeneratorTest.java @@ -97,6 +97,8 @@ static Stream fileSpecToProcess() { OpenApiGeneratorFixtures.validateValidationAnnotationsLombok(SPRING_BOOT_VERSION)), Arguments.of("testCreateDTO", OpenApiGeneratorFixtures.TEST_CREATE_DTO, OpenApiGeneratorFixtures.validateCreateDTO()), + Arguments.of("testCreateBasicDTO", OpenApiGeneratorFixtures.TEST_CREATE_BASIC_DTO, + OpenApiGeneratorFixtures.validateCreateBasicDTO()), Arguments.of("testIssueFaker", OpenApiGeneratorFixtures.TEST_ISSUE_FAKER, OpenApiGeneratorFixtures.validateIssueFaker()), Arguments.of("testDateTime", OpenApiGeneratorFixtures.TEST_DATE_TIME, diff --git a/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/api-test.yml b/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/api-test.yml new file mode 100644 index 00000000..fff9f7e5 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/api-test.yml @@ -0,0 +1,67 @@ +--- +openapi: "3.0.0" +info: + contact: + name: Os3 Team + email: os3-info@sngular.com + version: 1.0.0 + title: Testing example file + license: + name: MIT + description: Testing example file +servers: +- url: http://localhost:8080/v1 +tags: +- name: testAdditionalProperties + description: Test service +paths: + /test: + summary: testCreateDTO + get: + summary: testCreateDTO + description: Test File for SCC MultiApi Plugin. + tags: + - test + operationId: testCreateDTO + responses: + '200': + $ref: '#/components/responses/testCreate' +components: + responses: + testCreate: + description: An object with additional properties + content: + application/json: + schema: + $ref: '#/components/schemas/test' + schemas: + test: + type: object + required: + - id + - age + - properties + properties: + id: + $ref: "#/components/schemas/strProperty" + age: + type: number + format: int32 + properties: + $ref: "#/components/schemas/strProperty" + address: + type: object + required: + - country + - city + properties: + street: + $ref: "#/components/schemas/strProperty" + country: + $ref: "#/components/schemas/booleanProperty" + city: + $ref: "#/components/schemas/strProperty" + strProperty: + type: string + booleanProperty: + type: boolean diff --git a/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/TestApi.java b/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/TestApi.java new file mode 100644 index 00000000..61745f02 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/TestApi.java @@ -0,0 +1,46 @@ +package com.sngular.multifileplugin.testCreateBasicDTO; + +import java.util.Optional; +import java.util.List; +import java.util.Map; +import javax.validation.Valid; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import org.springframework.http.MediaType; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.NativeWebRequest; + +import com.sngular.multifileplugin.testCreateBasicDTO.model.TestDTO; + +public interface TestApi { + + /** + * GET /test: testCreateDTO + * @return An object with additional properties; (status code 200) + */ + + @Operation( + operationId = "testCreateDTO", + summary = "testCreateDTO", + tags = {"test"}, + responses = { + @ApiResponse(responseCode = "200", description = "An object with additional properties", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDTO.class))) + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = "/test", + produces = {"application/json"} + ) + + default ResponseEntity testCreateDTO() { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + +} diff --git a/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/model/AddressDTO.java b/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/model/AddressDTO.java new file mode 100644 index 00000000..2cdb6a65 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/model/AddressDTO.java @@ -0,0 +1,33 @@ +package com.sngular.multifileplugin.testCreateBasicDTO.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +import lombok.Data; +import lombok.NonNull; +import lombok.extern.jackson.Jacksonized; + +@Data +public class AddressDTO { + + @JsonProperty(value ="country") + @NonNull + private Boolean country; + + @JsonProperty(value ="city") + @NonNull + private String city; + + @JsonProperty(value ="street") + private String street; + + + @Builder + @Jacksonized + private AddressDTO(@NonNull Boolean country, @NonNull String city, String street) { + this.country = country; + this.city = city; + this.street = street; + + } + +} diff --git a/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/model/TestDTO.java b/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/model/TestDTO.java new file mode 100644 index 00000000..75f508b0 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testCreateBasicDTO/assets/model/TestDTO.java @@ -0,0 +1,39 @@ +package com.sngular.multifileplugin.testCreateBasicDTO.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.math.BigDecimal; +import lombok.Builder; +import lombok.Data; +import lombok.NonNull; +import lombok.extern.jackson.Jacksonized; + +@Data +public class TestDTO { + + @JsonProperty(value ="properties") + @NonNull + private String properties; + + @JsonProperty(value ="id") + @NonNull + private String id; + + @JsonProperty(value ="address") + private AddressDTO address; + + @JsonProperty(value ="age") + @NonNull + private BigDecimal age; + + + @Builder + @Jacksonized + private TestDTO(@NonNull String properties, @NonNull String id, AddressDTO address, @NonNull BigDecimal age) { + this.properties = properties; + this.id = id; + this.address = address; + this.age = age; + + } + +} diff --git a/scs-multiapi-gradle-plugin/build.gradle b/scs-multiapi-gradle-plugin/build.gradle index ac91fe90..78fb0d25 100644 --- a/scs-multiapi-gradle-plugin/build.gradle +++ b/scs-multiapi-gradle-plugin/build.gradle @@ -20,7 +20,7 @@ repositories { } group = 'com.sngular' -version = '5.3.0' +version = '5.3.1' def SCSMultiApiPluginGroupId = group def SCSMultiApiPluginVersion = version @@ -30,7 +30,7 @@ dependencies { shadow localGroovy() shadow gradleApi() - implementation 'com.sngular:multiapi-engine:5.3.0' + implementation 'com.sngular:multiapi-engine:5.3.1' testImplementation 'org.assertj:assertj-core:3.24.2' testImplementation 'com.puppycrawl.tools:checkstyle:10.12.3' } @@ -98,7 +98,7 @@ testing { integrationTest(JvmTestSuite) { dependencies { - implementation 'com.sngular:scs-multiapi-gradle-plugin:5.3.0' + implementation 'com.sngular:scs-multiapi-gradle-plugin:5.3.1' implementation 'org.assertj:assertj-core:3.24.2' } diff --git a/scs-multiapi-maven-plugin/pom.xml b/scs-multiapi-maven-plugin/pom.xml index bfc91d95..0189e6c5 100644 --- a/scs-multiapi-maven-plugin/pom.xml +++ b/scs-multiapi-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.sngular scs-multiapi-maven-plugin - 5.3.0 + 5.3.1 maven-plugin AsyncApi - OpenApi Code Generator Maven Plugin @@ -243,7 +243,7 @@ com.sngular multiapi-engine - 5.3.0 + 5.3.1 org.apache.maven