From 4b86ec3cf5b2757e8656da4a6260f0879dc7caca Mon Sep 17 00:00:00 2001 From: Suso <126153639+5uso-sng@users.noreply.github.com> Date: Wed, 12 Apr 2023 12:53:10 +0200 Subject: [PATCH 1/3] 176 missing dates types in openapi (#187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #177 Fix embedded object generation * Slight code cleanup * Add missing license notice * Added date types to FieldObjectType mappings * Type constants consistency We somehow had these duplicated in three different places, with inconsistent capitalization * Added date and date-time test * #176 Added support for date and date-time formats * #176 Added Zoned and Offset time options Configured within the SpecFile * Fixed checkstyle violations * Updated version #185 Should be a patch, so changing the version number to 4.6.0 should work regardless of merge order * Make empty restrictionProperties the default * Post-merge checkstyle * Updated readme with useTimeType * Change deploy parameters --------- Co-authored-by: Jose Enrique García Maciñeiras --- .github/workflows/maven-central-push.yml | 2 +- README.md | 21 +- multiapi-engine/pom.xml | 3 +- .../asyncapi/util/MapperContentUtil.java | 23 +- .../plugin/openapi/OpenApiGenerator.java | 2 +- .../openapi/model/BasicTypeConstants.java | 29 -- .../openapi/model/SchemaFieldObject.java | 5 +- .../openapi/model/SchemaFieldObjectType.java | 157 +++++---- .../plugin/openapi/model/TypeConstants.java | 65 ++++ .../plugin/openapi/parameter/SpecFile.java | 5 + .../openapi/utils/MapperContentUtil.java | 316 ++++++++++-------- .../plugin/openapi/utils/MapperPathUtil.java | 71 ++-- .../plugin/openapi/utils/MapperUtil.java | 69 ++-- .../templates/openapi/templateSchema.ftlh | 34 +- .../openapi/templateSchemaWithLombok.ftlh | 12 +- .../openapi/OpenApiGeneratorFixtures.java | 93 ++++++ .../plugin/openapi/OpenApiGeneratorTest.java | 8 +- .../testComplexAnyOf/assets/ApiSchemaDTO.java | 2 +- .../assets/ApiSequenceFieldDTO.java | 2 +- .../testDateTime/api-test.yml | 30 ++ .../testDateTime/assets/TestApi.java | 45 +++ .../assets/model/TestDateDTO.java | 30 ++ .../testDateTimeOffset/api-test.yml | 30 ++ .../testDateTimeOffset/assets/TestApi.java | 45 +++ .../assets/model/TestDateDTO.java | 29 ++ .../testDateTimeZoned/api-test.yml | 30 ++ .../testDateTimeZoned/assets/TestApi.java | 45 +++ .../assets/model/TestDateDTO.java | 29 ++ scs-multiapi-gradle-plugin/build.gradle | 6 +- scs-multiapi-maven-plugin/pom.xml | 23 +- 30 files changed, 871 insertions(+), 390 deletions(-) delete mode 100644 multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/BasicTypeConstants.java create mode 100644 multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/TypeConstants.java create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTime/api-test.yml create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTime/assets/TestApi.java create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTime/assets/model/TestDateDTO.java create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/api-test.yml create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/assets/TestApi.java create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/assets/model/TestDateDTO.java create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/api-test.yml create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/assets/TestApi.java create mode 100644 multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/assets/model/TestDateDTO.java diff --git a/.github/workflows/maven-central-push.yml b/.github/workflows/maven-central-push.yml index 464af80d..ba23c4a0 100644 --- a/.github/workflows/maven-central-push.yml +++ b/.github/workflows/maven-central-push.yml @@ -71,7 +71,7 @@ jobs: # Uses production profile to sign with gpg plugin run: | cd scs-multiapi-maven-plugin - mvn deploy -P production + mvn deploy -DskipLocalStaging=true -P production --file pom-xml env: MAVEN_USERNAME: ${{ secrets.JIRAID }} MAVEN_CENTRAL_TOKEN: ${{ secrets.JIRAPASS }} diff --git a/README.md b/README.md index 6f9e98e0..803402fa 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ Maven and Gradle - [AsyncApi Generator](#asyncapi-generator) - [Configuration](#configuration) - [Generated Sources Folder](#generated-sources-folder) - - [How apiPackage is setted?](#how-apipackage-is-setted) - - [How modelPackage is setted?](#how-modelpackage-is-setted) + - [How is apiPackage set?](#how-is-apipackage-set) + - [How is modelPackage set?](#how-is-modelpackage-set) - [Class Generation](#class-generation) - [Consumer and Supplier classes](#consumer-and-supplier-classes) - [Method interfaces](#method-interfaces) @@ -216,8 +216,8 @@ YML files as you want. **filePath** parameter, that expects to receive the path to the file. Using the plugin in this way, you can't configure the model package or the api package in the pom file, neither other options, so they will be configured as - its explained in [apiPackage](#how-apipackage-is-setted) and - [modelPackage](#how-modelpackage-is-setted) sections. + its explained in [apiPackage](#how-is-apipackage-set) and + [modelPackage](#how-is-modelpackage-set) sections. This way it's limited to the usage of Consumer and Supplier methods. ```xml @@ -301,7 +301,7 @@ can be configured in the plugin. result as `EntityClassDTO`. This parameter is optional. - **apiPackage**: This parameter receive a package name, where the generated classes will be generated. This parameter is optional. - Check [how the apiPackage is setted](#how-apipackage-is-setted) for + Check [how is the apiPackage set](#how-is-apipackage-set) for more information about how this parameter works, and the values it could have. - **modelPackage**: This parameter receives a package name, where the entities @@ -311,7 +311,7 @@ can be configured in the plugin. **Note that the plugin doesn't create the entities neither checks their existence**, it takes their names from the YML file and assume that they are created by the user. As the previous parameter, this is also optional. - Check [how the modelPackage is setted](#how-modelpackage-is-setted) for more + Check [how is the modelPackage set](#how-is-modelpackage-set) for more information about how his parameter works, and the values it could have. The configuration of `consumer`, `supplier` and `streamBridge` are independent. @@ -330,7 +330,7 @@ By default, it's values is `generated-sources`, so the files will be in the pom.xml file, as in the example above, files will remain in `.../target/sources-generated/apigenerator/...`. -### How apiPackage is setted? +### How is apiPackage set? The api package could be set in three different ways. @@ -342,7 +342,7 @@ The api package could be set in three different ways. plugin will use a default package name, that is stablished as `com.sngular.apigenerator.asyncapi`. -### How modelPackage is setted? +### How is modelPackage set? The model package could be set in four different ways. @@ -666,14 +666,15 @@ that will be used. Each specFile has their own configuration: | Name | Description | Example | |--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| | filePath | Path where the yaml is located | ${project.basedir}/src/main/resources/api/api.yml | -| apiPackage | Path where the api interface will be located | com.sngular.apigenerator.openapi | -| modelPackage | Path where the models will be located | com.sngular.apigenerator.openapi.model | +| apiPackage | Path where the api interface will be located | com.sngular.apigenerator.openapi | +| modelPackage | Path where the models will be located | com.sngular.apigenerator.openapi.model | | modelNamePrefix | Prefix that will be used ahead of every model´s name | Api | | modelNameSuffix | Suffix that will be used after every model´s name | DTO | | callMode | Boolean value to decide if you want to generate the api for external calls. **Use RestClient by default. It´s initialized to false by default** | false | | useTagsGroup | Boolean value to decide if using tags instead of an URL for group the API. **It´s initialized to false by default** | false | | useLombokModelAnnotation | Boolean value to decide if you want your models with Lombok or not **It´s initialized to false by default** | false | | isReactive | Boolean value to decide if you want to generate the api with responses in Mono/Flux Reactor types. If callmode = true use WebClient instead of RestClient. **It´s initialized to false by default** | false | +| useTimeType | Enum TimeType value. Controls the types used when generating dates. Can be local, zoned, or offset. **Initialized to TimeType.LOCAL by default** | TimeType.OFFSET | As the configuration options already indicate, the data model will also be created within the specified path.This model will be created with the indicated diff --git a/multiapi-engine/pom.xml b/multiapi-engine/pom.xml index f8ff315f..78f0af1c 100644 --- a/multiapi-engine/pom.xml +++ b/multiapi-engine/pom.xml @@ -4,7 +4,7 @@ com.sngular multiapi-engine - 4.5.2 + 4.6.0 jar @@ -241,6 +241,7 @@ com.github.ekryd.sortpom sortpom-maven-plugin + 3.2.1 diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/asyncapi/util/MapperContentUtil.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/asyncapi/util/MapperContentUtil.java index 11b8eac9..3b6125c9 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/asyncapi/util/MapperContentUtil.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/asyncapi/util/MapperContentUtil.java @@ -323,41 +323,42 @@ private static void handleItems(final JsonNode schema, final Collection private static void setFieldProperties(final SchemaFieldObject fieldObject, final JsonNode schema) { final Iterator> iterator = schema.fields(); Entry current; + final SchemaFieldObjectProperties props = fieldObject.getRestrictions(); while (iterator.hasNext()) { current = iterator.next(); switch (current.getKey()) { case "minimum": - fieldObject.getRestrictions().setMinimum(current.getValue().asText()); + props.setMinimum(current.getValue().asText()); break; case "maximum": - fieldObject.getRestrictions().setMaximum(current.getValue().asText()); + props.setMaximum(current.getValue().asText()); break; case "exclusiveMinimum": - fieldObject.getRestrictions().setExclusiveMinimum(current.getValue().booleanValue()); + props.setExclusiveMinimum(current.getValue().booleanValue()); break; case "exclusiveMaximum": - fieldObject.getRestrictions().setExclusiveMaximum(current.getValue().booleanValue()); + props.setExclusiveMaximum(current.getValue().booleanValue()); break; case "maxItems": - fieldObject.getRestrictions().setMaxItems(current.getValue().intValue()); + props.setMaxItems(current.getValue().intValue()); break; case "maxLength": - fieldObject.getRestrictions().setMaxLength(current.getValue().intValue()); + props.setMaxLength(current.getValue().intValue()); break; case "minItems": - fieldObject.getRestrictions().setMinItems(current.getValue().intValue()); + props.setMinItems(current.getValue().intValue()); break; case "minLength": - fieldObject.getRestrictions().setMinLength(current.getValue().intValue()); + props.setMinLength(current.getValue().intValue()); break; case "pattern": - fieldObject.getRestrictions().setPattern(current.getValue().toString().replaceAll("\"", "")); + props.setPattern(current.getValue().toString().replaceAll("\"", "")); break; case "uniqueItems": - fieldObject.getRestrictions().setUniqueItems(current.getValue().booleanValue()); + props.setUniqueItems(current.getValue().booleanValue()); break; case "multipleOf": - fieldObject.getRestrictions().setMultipleOf(current.getValue().asText()); + props.setMultipleOf(current.getValue().asText()); break; default: break; 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 e274e9e2..67504241 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 @@ -196,7 +196,7 @@ private void addAuthentications(final AuthObject authObject) { } } - private void createModelTemplate(final SpecFile specFile, final OpenAPI openAPI) throws TemplateException, IOException { + private void createModelTemplate(final SpecFile specFile, final OpenAPI openAPI) { final String fileModelToSave = processPath(specFile.getModelPackage(), true); final var modelPackage = processModelPackage(specFile.getModelPackage()); final var basicSchemaMap = OpenApiUtil.processBasicSchemas(openAPI); diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/BasicTypeConstants.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/BasicTypeConstants.java deleted file mode 100644 index ae12b05c..00000000 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/BasicTypeConstants.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * * License, v. 2.0. If a copy of the MPL was not distributed with this - * * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package com.sngular.api.generator.plugin.openapi.model; - -import java.util.Set; - -public final class BasicTypeConstants { - - public static final String NUMBER = "number"; - - public static final String STRING = "string"; - - public static final String BOOLEAN = "boolean"; - - public static final String INTEGER = "integer"; - - public static final String ARRAY = "array"; - - public static final Set BASIC_OBJECT_TYPE = Set.of(NUMBER, STRING, BOOLEAN, INTEGER, ARRAY); - - private BasicTypeConstants() { - - } - -} diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/SchemaFieldObject.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/SchemaFieldObject.java index 2a74c9f8..4319287e 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/SchemaFieldObject.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/SchemaFieldObject.java @@ -15,8 +15,6 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.OBJECT; - @Data @Builder @NoArgsConstructor @@ -27,8 +25,9 @@ public class SchemaFieldObject { private String baseName; @Default - private SchemaFieldObjectType dataType = new SchemaFieldObjectType(OBJECT); + private SchemaFieldObjectType dataType = new SchemaFieldObjectType(TypeConstants.OBJECT); + @Default private SchemaFieldObjectProperties restrictionProperties = new SchemaFieldObjectProperties(); private String importClass; diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/SchemaFieldObjectType.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/SchemaFieldObjectType.java index dd534c5b..989f32cb 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/SchemaFieldObjectType.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/SchemaFieldObjectType.java @@ -1,140 +1,137 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + package com.sngular.api.generator.plugin.openapi.model; -import java.util.Arrays; -import java.util.Iterator; +import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Map; import java.util.Objects; -import java.util.Set; import lombok.Data; @Data public class SchemaFieldObjectType { - public static final String OBJECT = "Object"; - - public static final String ARRAY = "Array"; - - public static final String MAP = "Map"; - - public static final String BIG_DECIMAL = "BigDecimal"; - - public static final String INTEGER = "Integer"; - - public static final String DOUBLE = "Double"; - - public static final String FLOAT = "Float"; - - public static final String LONG = "Long"; - - public static final String STRING = "String"; - - public static final String ENUM = "Enum"; - - public static final Set BASIC_TYPES = Set.of(STRING, INTEGER, OBJECT); - - private static final Map typeMappings = Map.of( - OBJECT, "Object", - ARRAY, "List", - MAP, "Map", - BIG_DECIMAL, "BigDecimal", - INTEGER, "Integer", - DOUBLE, "Double", - FLOAT, "Float", - LONG, "Long", - STRING, "String", - ENUM, "Enum" + private static final Map TYPE_MAPPINGS = Map.ofEntries( + new SimpleImmutableEntry<>(TypeConstants.OBJECT, "Object"), + new SimpleImmutableEntry<>(TypeConstants.ARRAY, "List"), + new SimpleImmutableEntry<>(TypeConstants.MAP, "Map"), + new SimpleImmutableEntry<>(TypeConstants.BIG_DECIMAL, "BigDecimal"), + new SimpleImmutableEntry<>(TypeConstants.INTEGER, "Integer"), + new SimpleImmutableEntry<>(TypeConstants.DOUBLE, "Double"), + new SimpleImmutableEntry<>(TypeConstants.FLOAT, "Float"), + new SimpleImmutableEntry<>(TypeConstants.LONG, "Long"), + new SimpleImmutableEntry<>(TypeConstants.STRING, "String"), + new SimpleImmutableEntry<>(TypeConstants.ENUM, "Enum"), + new SimpleImmutableEntry<>(TypeConstants.LOCALDATE, "LocalDate"), + new SimpleImmutableEntry<>(TypeConstants.LOCALDATETIME, "LocalDateTime"), + new SimpleImmutableEntry<>(TypeConstants.ZONEDDATE, "ZonedDateTime"), + new SimpleImmutableEntry<>(TypeConstants.ZONEDDATETIME, "ZonedDateTime"), + new SimpleImmutableEntry<>(TypeConstants.OFFSETDATE, "OffsetDateTime"), + new SimpleImmutableEntry<>(TypeConstants.OFFSETDATETIME, "OffsetDateTime") ); - private static final Map implTypeMappings = Map.of( - OBJECT, "Object", - ARRAY, "ArrayList", - MAP, "HashMap", - BIG_DECIMAL, "BigDecimal", - INTEGER, "Integer", - DOUBLE, "Double", - FLOAT, "Float", - LONG, "Long", - STRING, "String", - ENUM, "Enum" + private static final Map IMPL_TYPE_MAPPINGS = Map.ofEntries( + new SimpleImmutableEntry<>(TypeConstants.OBJECT, "Object"), + new SimpleImmutableEntry<>(TypeConstants.ARRAY, "ArrayList"), + new SimpleImmutableEntry<>(TypeConstants.MAP, "HashMap"), + new SimpleImmutableEntry<>(TypeConstants.BIG_DECIMAL, "BigDecimal"), + new SimpleImmutableEntry<>(TypeConstants.INTEGER, "Integer"), + new SimpleImmutableEntry<>(TypeConstants.DOUBLE, "Double"), + new SimpleImmutableEntry<>(TypeConstants.FLOAT, "Float"), + new SimpleImmutableEntry<>(TypeConstants.LONG, "Long"), + new SimpleImmutableEntry<>(TypeConstants.STRING, "String"), + new SimpleImmutableEntry<>(TypeConstants.ENUM, "Enum"), + new SimpleImmutableEntry<>(TypeConstants.LOCALDATE, "LocalDate"), + new SimpleImmutableEntry<>(TypeConstants.LOCALDATETIME, "LocalDateTime"), + new SimpleImmutableEntry<>(TypeConstants.ZONEDDATE, "ZonedDateTime"), + new SimpleImmutableEntry<>(TypeConstants.ZONEDDATETIME, "ZonedDateTime"), + new SimpleImmutableEntry<>(TypeConstants.OFFSETDATE, "OffsetDateTime"), + new SimpleImmutableEntry<>(TypeConstants.OFFSETDATETIME, "OffsetDateTime") ); private SchemaFieldObjectType innerType; private final String baseType; - public SchemaFieldObjectType(String baseType, SchemaFieldObjectType innerType) { + public SchemaFieldObjectType(final String baseType, final SchemaFieldObjectType innerType) { this.innerType = innerType; this.baseType = baseType; } - public SchemaFieldObjectType(String type) { + public SchemaFieldObjectType(final String type) { this.innerType = null; this.baseType = type; } - public static SchemaFieldObjectType fromTypeList(String... types) { - Iterator typeIterator = Arrays.stream(types).iterator(); - return constructTypeFromList(typeIterator); - } + public static SchemaFieldObjectType fromTypeList(final String... types) { + final SchemaFieldObjectType result = new SchemaFieldObjectType(types[0], null); + SchemaFieldObjectType objectType = result; - private static SchemaFieldObjectType constructTypeFromList(Iterator types) { - if (!types.hasNext()) { - return null; + for (int i = 1; i < types.length; i++) { + objectType.innerType = new SchemaFieldObjectType(types[i], null); + objectType = objectType.innerType; } - return new SchemaFieldObjectType(types.next(), constructTypeFromList(types)); + return result; } - public void setDeepType(SchemaFieldObjectType type) { - if (Objects.isNull(innerType)) { - innerType = type; - return; + public void setDeepType(final SchemaFieldObjectType type) { + SchemaFieldObjectType parentType = this; + while (Objects.nonNull(parentType.innerType)) { + parentType = parentType.innerType; } - innerType.setDeepType(type); + parentType.innerType = type; } - public void setDeepType(String type) { + public void setDeepType(final String type) { setDeepType(new SchemaFieldObjectType(type)); } - public boolean containsType(String type) { - return type.equals(baseType) || (Objects.nonNull(innerType) && innerType.containsType(type)); + public boolean containsType(final String type) { + return type.equalsIgnoreCase(baseType) || Objects.nonNull(innerType) && innerType.containsType(type); } - private String mapIntoString(Map mappings) { - String baseString = mappings.getOrDefault(baseType, baseType); - if (!baseString.contains("?")) { - return baseString; - } + private String mapIntoString(final Map mappings) { + final String baseString = mappings.getOrDefault(baseType, baseType); + final boolean hasInner = baseString.contains("?"); - if (Objects.isNull(innerType)) { + if (hasInner && Objects.isNull(innerType)) { throw new RuntimeException(String.format("Field object type '%s' missing an inner type", baseType)); } - return baseString.replace("?", innerType.mapIntoString(typeMappings)); + return hasInner ? baseString.replace("?", innerType.mapIntoString(TYPE_MAPPINGS)) : baseString; } + @SuppressWarnings("unused") // This method is invoked by templates public String getImplementationTypeString() { - return mapIntoString(implTypeMappings); + return mapIntoString(IMPL_TYPE_MAPPINGS); } @Override public String toString() { - return mapIntoString(typeMappings); + return mapIntoString(TYPE_MAPPINGS); } @Override public boolean equals(final Object obj) { - if (!(obj instanceof SchemaFieldObjectType)) { - return false; + boolean result = false; + if (obj instanceof SchemaFieldObjectType) { + final SchemaFieldObjectType other = (SchemaFieldObjectType) obj; + final boolean baseTypeIsEqual = baseType.equals(other.baseType); + final boolean innerTypeIsEqual = Objects.isNull(innerType) ? Objects.isNull(other.innerType) : innerType.equals(other.innerType); + result = baseTypeIsEqual && innerTypeIsEqual; } - SchemaFieldObjectType other = (SchemaFieldObjectType) obj; - final boolean baseTypeIsEqual = baseType.equals(other.baseType); - final boolean innerTypeIsEqual = Objects.isNull(innerType) ? Objects.isNull(other.innerType) : innerType.equals(other.innerType); + return result; + } - return baseTypeIsEqual && innerTypeIsEqual; + @Override + public int hashCode() { + return Objects.hash(Objects.isNull(innerType) ? 0 : innerType.hashCode(), baseType); } } 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 new file mode 100644 index 00000000..e8fba9c3 --- /dev/null +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/model/TypeConstants.java @@ -0,0 +1,65 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package com.sngular.api.generator.plugin.openapi.model; + +import java.util.Set; + +public final class TypeConstants { + + public static final String NUMBER = "number"; + + public static final String BOOLEAN = "boolean"; + + public static final String OBJECT = "object"; + + public static final String ARRAY = "array"; + + public static final String MAP = "map"; + + public static final String BIG_DECIMAL = "bigDecimal"; + + public static final String INTEGER = "integer"; + + public static final String DOUBLE = "double"; + + public static final String FLOAT = "float"; + + public static final String LONG = "long"; + + public static final String STRING = "string"; + + public static final String ENUM = "enum"; + + public static final String LOCALDATE = "localdate"; + + public static final String LOCALDATETIME = "localdatetime"; + + public static final String ZONEDDATE = "zoneddate"; + + public static final String ZONEDDATETIME = "zoneddatetime"; + + public static final String OFFSETDATE = "offsetdate"; + + public static final String OFFSETDATETIME = "offsetdatetime"; + + public static final String INT_32 = "int32"; + + public static final String INT_64 = "int64"; + + public static final Set BASIC_OBJECT_TYPE = Set.of(NUMBER, STRING, BOOLEAN, INTEGER, ARRAY); + + public static final Set NO_IMPORT_TYPE = Set.of(STRING, INTEGER, OBJECT); + + public enum TimeType { + LOCAL, ZONED, OFFSET + } + + private TypeConstants() { + + } + +} diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/parameter/SpecFile.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/parameter/SpecFile.java index ba595f38..1db5ea54 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/parameter/SpecFile.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/parameter/SpecFile.java @@ -6,8 +6,10 @@ package com.sngular.api.generator.plugin.openapi.parameter; +import com.sngular.api.generator.plugin.openapi.model.TypeConstants.TimeType; import lombok.AllArgsConstructor; import lombok.Builder; +import lombok.Builder.Default; import lombok.Data; import lombok.NoArgsConstructor; @@ -36,4 +38,7 @@ public class SpecFile { private boolean useLombokModelAnnotation; private boolean isReactive; + + @Default + private TimeType useTimeType = TimeType.LOCAL; } diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperContentUtil.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperContentUtil.java index 138fc180..d361f789 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperContentUtil.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperContentUtil.java @@ -16,12 +16,14 @@ import com.sngular.api.generator.plugin.openapi.exception.BadDefinedEnumException; import com.sngular.api.generator.plugin.openapi.model.SchemaFieldObject; -import com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectProperties; import com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType; import com.sngular.api.generator.plugin.openapi.model.SchemaObject; +import com.sngular.api.generator.plugin.openapi.model.TypeConstants; import com.sngular.api.generator.plugin.openapi.parameter.SpecFile; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.ComposedSchema; +import io.swagger.v3.oas.models.media.DateSchema; +import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; @@ -30,18 +32,6 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.ARRAY; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.MAP; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.BIG_DECIMAL; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.OBJECT; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.ENUM; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.INTEGER; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.LONG; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.FLOAT; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.DOUBLE; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.STRING; -import static com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType.BASIC_TYPES; - public class MapperContentUtil { private static final String ADDITIONAL_PROPERTY_NAME = "AdditionalProperty"; @@ -113,16 +103,40 @@ private static List getImportList(final List fieldObj private static void getTypeImports(final HashMap> listHashMap, final SchemaFieldObject fieldObject) { final SchemaFieldObjectType type = fieldObject.getDataType(); - if (type.containsType(ARRAY)) { - listHashMap.computeIfAbsent(ARRAY, key -> List.of("java.util.List", "java.util.ArrayList")); + if (type.containsType(TypeConstants.ARRAY)) { + listHashMap.computeIfAbsent(TypeConstants.ARRAY, key -> List.of("java.util.List", "java.util.ArrayList")); + } + + if (type.containsType(TypeConstants.MAP)) { + listHashMap.computeIfAbsent(TypeConstants.MAP, key -> List.of("java.util.Map", "java.util.HashMap")); + } + + if (type.containsType(TypeConstants.BIG_DECIMAL)) { + listHashMap.computeIfAbsent(TypeConstants.BIG_DECIMAL, key -> List.of("java.math.BigDecimal")); + } + + if (type.containsType(TypeConstants.LOCALDATE)) { + listHashMap.computeIfAbsent(TypeConstants.LOCALDATE, key -> List.of("java.time.LocalDate")); + } + + if (type.containsType(TypeConstants.LOCALDATETIME)) { + listHashMap.computeIfAbsent(TypeConstants.LOCALDATETIME, key -> List.of("java.time.LocalDateTime")); + } + + if (type.containsType(TypeConstants.ZONEDDATE)) { + listHashMap.computeIfAbsent(TypeConstants.ZONEDDATETIME, key -> List.of("java.time.ZonedDateTime")); + } + + if (type.containsType(TypeConstants.ZONEDDATETIME)) { + listHashMap.computeIfAbsent(TypeConstants.ZONEDDATETIME, key -> List.of("java.time.ZonedDateTime")); } - if (type.containsType(MAP)) { - listHashMap.computeIfAbsent(MAP, key -> List.of("java.util.Map", "java.util.HashMap")); + if (type.containsType(TypeConstants.OFFSETDATE)) { + listHashMap.computeIfAbsent(TypeConstants.OFFSETDATETIME, key -> List.of("java.time.OffsetDateTime")); } - if (type.containsType(BIG_DECIMAL)) { - listHashMap.computeIfAbsent(BIG_DECIMAL, key -> List.of("java.math.BigDecimal")); + if (type.containsType(TypeConstants.OFFSETDATETIME)) { + listHashMap.computeIfAbsent(TypeConstants.OFFSETDATETIME, key -> List.of("java.time.OffsetDateTime")); } } @@ -141,14 +155,13 @@ private static List getFields( fieldObjectArrayList.addAll( processFieldObjectList(null, null, schema, specFile, totalSchemas, compositedSchemas, antiLoopList)); } - } else if (ARRAY.equalsIgnoreCase(schema.getType())) { + } else if (TypeConstants.ARRAY.equalsIgnoreCase(schema.getType())) { final ArraySchema arraySchema = (ArraySchema) schema; final String itemType = Objects.nonNull(arraySchema.getItems().get$ref()) ? getRef(arraySchema.getItems(), specFile) : arraySchema.getItems().getType(); final var field = SchemaFieldObject.builder() .baseName("items") - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(ARRAY, itemType)) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.ARRAY, itemType)) .build(); fieldObjectArrayList.add(field); } else if (Objects.nonNull(schema.getAllOf())) { @@ -198,7 +211,6 @@ private static List processAnyOfOneOf( if (compositedSchemas.containsKey(schemaName)) { fieldObjectArrayList.add(SchemaFieldObject .builder() - .restrictionProperties(new SchemaFieldObjectProperties()) .baseName(schemaName) .dataType(new SchemaFieldObjectType(schemaName)) .build()); @@ -223,24 +235,13 @@ private static List processFieldObjectList( final Map compositedSchemas, final List antiLoopList) { final var fieldObjectArrayList = new LinkedList(); - if (ARRAY.equalsIgnoreCase(schema.getType())) { - fieldObjectArrayList.addAll( - processArray(fieldName, className, schema, specFile, totalSchemas, compositedSchemas, antiLoopList)); + if (TypeConstants.ARRAY.equalsIgnoreCase(schema.getType())) { + fieldObjectArrayList.addAll(processArray(fieldName, className, schema, specFile, totalSchemas, compositedSchemas, antiLoopList)); } else if (schema instanceof MapSchema) { - if (OBJECT.equalsIgnoreCase(schema.getType()) && Objects.nonNull(schema.getProperties())) { - schema.getProperties().forEach( - processProperties(totalSchemas, compositedSchemas, fieldObjectArrayList, specFile, schema, antiLoopList)); - } - - if (Objects.nonNull(schema.getAdditionalProperties())) { - fieldObjectArrayList.addAll( - processAdditionalProperties(fieldName, className, schema, specFile, totalSchemas, compositedSchemas, - antiLoopList)); - } + fieldObjectArrayList.addAll(processMap(fieldName, schema, specFile, totalSchemas, compositedSchemas, antiLoopList)); } else if (Objects.nonNull(schema.get$ref())) { final String refSchemaName = getRef(schema, specFile); final var field = SchemaFieldObject.builder() - .restrictionProperties(new SchemaFieldObjectProperties()) .baseName(fieldName) .dataType(new SchemaFieldObjectType(MapperUtil.getSimpleType(schema, specFile))) .build(); @@ -249,7 +250,6 @@ private static List processFieldObjectList( } else if (!(schema instanceof ObjectSchema || schema instanceof ComposedSchema)) { final var field = SchemaFieldObject .builder() - .restrictionProperties(new SchemaFieldObjectProperties()) .baseName(fieldName) .dataType(new SchemaFieldObjectType(MapperUtil.getSimpleType(schema, specFile))) .build(); @@ -259,42 +259,10 @@ private static List processFieldObjectList( fieldObjectArrayList.add(SchemaFieldObject .builder() .baseName(fieldName) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(new SchemaFieldObjectType(OBJECT)) + .dataType(new SchemaFieldObjectType(TypeConstants.OBJECT)) .build()); } else if (schema instanceof ObjectSchema) { - if (ObjectUtils.allNull(className, fieldName)) { - schema.getProperties().forEach( - processProperties(totalSchemas, compositedSchemas, fieldObjectArrayList, specFile, schema, antiLoopList)); - } else if (antiLoopList.contains(className)) { - fieldObjectArrayList - .add(SchemaFieldObject - .builder() - .baseName(className) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(OBJECT, MapperUtil.getPojoName(className, specFile))) - .build()); - } else if (antiLoopList.contains(fieldName)) { - fieldObjectArrayList - .add(SchemaFieldObject - .builder() - .baseName(fieldName) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(OBJECT, MapperUtil.getPojoName(fieldName, specFile))) - .build()); - } else { - final String name = StringUtils.defaultIfBlank(className, fieldName); - compositedSchemas.putAll( - mapComponentToSchemaObject(totalSchemas, compositedSchemas, antiLoopList, schema, name, specFile, - specFile.getModelPackage())); - fieldObjectArrayList - .add(SchemaFieldObject - .builder() - .baseName(name) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(OBJECT, MapperUtil.getPojoName(name, specFile))) - .build()); - } + fieldObjectArrayList.addAll(processObject(fieldName, className, schema, specFile, totalSchemas, compositedSchemas, antiLoopList)); } else { final var composedSchemaName = StringUtils.defaultIfBlank(className, fieldName); var schemaObjectComposed = compositedSchemas.get(composedSchemaName); @@ -307,7 +275,6 @@ private static List processFieldObjectList( fieldObjectArrayList.add(SchemaFieldObject .builder() .baseName(fieldName) - .restrictionProperties(new SchemaFieldObjectProperties()) .dataType(SchemaFieldObjectType.fromTypeList(schemaObjectComposed.getClassName(), schemaObjectComposed.getClassName())) .build()); } @@ -332,30 +299,30 @@ private static List processObjectProperty( final Map totalSchemas, final String key, final Schema value, final Map compositedSchemas, final SpecFile specFile, final Schema schema, final List antiLoopList) { final List fieldObjectArrayList = new LinkedList<>(); + final SchemaFieldObject field; if (Objects.nonNull(value.get$ref())) { final var typeName = cleanRefName(value); - if (!antiLoopList.contains(typeName) - && (totalSchemas.containsKey(typeName) && Objects.nonNull( - totalSchemas.get(typeName).getType()) && totalSchemas.get(typeName).getType().equalsIgnoreCase(ARRAY) - || value.get$ref().contains(key))) { + + if (!antiLoopList.contains(typeName) && totalSchemas.containsKey(typeName) && Objects.nonNull(totalSchemas.get(typeName).getType()) + && totalSchemas.get(typeName).getType().equalsIgnoreCase(TypeConstants.ARRAY) || value.get$ref().contains(key)) { antiLoopList.add(typeName); - fieldObjectArrayList.addAll( - processFieldObjectList(key, typeName, totalSchemas.get(typeName), specFile, totalSchemas, compositedSchemas, - antiLoopList)); + fieldObjectArrayList.addAll(processFieldObjectList(key, typeName, totalSchemas.get(typeName), specFile, totalSchemas, compositedSchemas, antiLoopList)); } else { fieldObjectArrayList.add(SchemaFieldObject .builder() .baseName(key) - .restrictionProperties(new SchemaFieldObjectProperties()) .dataType(SchemaFieldObjectType.fromTypeList(MapperUtil.getSimpleType(totalSchemas.get(typeName), specFile), MapperUtil.getPojoName(typeName, specFile))) .build()); } + } else if (TypeConstants.STRING.equalsIgnoreCase(value.getType())) { + field = processStringProperty(key, value, specFile); + setFieldType(field, value, schema, specFile, key); + fieldObjectArrayList.add(field); } else if (isBasicType(value)) { field = SchemaFieldObject .builder() - .restrictionProperties(new SchemaFieldObjectProperties()) .baseName(key) .dataType(new SchemaFieldObjectType(MapperUtil.getSimpleType(value, specFile))) .build(); @@ -363,12 +330,22 @@ private static List processObjectProperty( setFieldType(field, value, schema, specFile, key); fieldObjectArrayList.add(field); } else { - fieldObjectArrayList.addAll( - processFieldObjectList(key, key, value, specFile, totalSchemas, compositedSchemas, antiLoopList)); + fieldObjectArrayList.addAll(processFieldObjectList(key, key, value, specFile, totalSchemas, compositedSchemas, antiLoopList)); } return fieldObjectArrayList; } + private static SchemaFieldObject processStringProperty(final String propertyName, final Schema schema, final SpecFile specFile) { + final String resultingType = schema instanceof DateSchema ? getDateType(specFile) : (schema instanceof DateTimeSchema ? getDateTimeType(specFile) : TypeConstants.STRING); + final SchemaFieldObject field = SchemaFieldObject + .builder() + .baseName(propertyName) + .dataType(new SchemaFieldObjectType(resultingType)) + .build(); + addPropertiesToFieldObject(field, schema); + return field; + } + private static void addPropertiesToFieldObject(final SchemaFieldObject fieldObject, final Schema value) { fieldObject.getRestrictionProperties().setPattern(value.getPattern()); fieldObject.getRestrictionProperties().setMaxItems(value.getMaxItems()); @@ -398,8 +375,7 @@ private static List processArray( fieldObjectArrayList.add(SchemaFieldObject .builder() .baseName(fieldName) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(new SchemaFieldObjectType(OBJECT)) + .dataType(new SchemaFieldObjectType(TypeConstants.OBJECT)) .build()); } else { final var items = schema.getItems(); @@ -407,9 +383,8 @@ private static List processArray( final String refSchemaName = getRef(items, specFile); final var field = SchemaFieldObject .builder() - .restrictionProperties(new SchemaFieldObjectProperties()) .baseName(fieldName) - .dataType(SchemaFieldObjectType.fromTypeList(ARRAY, MapperUtil.getSimpleType(items, specFile))) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.ARRAY, MapperUtil.getSimpleType(items, specFile))) .build(); setFieldType(field, items, items, specFile, refSchemaName); fieldObjectArrayList.add(field); @@ -425,25 +400,22 @@ private static List processArray( fieldObjectArrayList.add(SchemaFieldObject .builder() .baseName(fieldName) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(ARRAY, schemaObjectComposed.getClassName())) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.ARRAY, schemaObjectComposed.getClassName())) .importClass(schemaObjectComposed.getClassName()) .build()); } else if (Objects.nonNull(items.getProperties())) { compositedSchemas.putAll(mapComponentToSchemaObject(totalSchemas, items, fieldName, specFile)); fieldObjectArrayList.add(SchemaFieldObject .builder() - .restrictionProperties(new SchemaFieldObjectProperties()) .baseName(fieldName) - .dataType(SchemaFieldObjectType.fromTypeList(ARRAY, MapperUtil.getPojoName(fieldName, specFile))) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.ARRAY, MapperUtil.getPojoName(fieldName, specFile))) .build()); } else { final SchemaFieldObject field = SchemaFieldObject - .builder() - .restrictionProperties(new SchemaFieldObjectProperties()) - .baseName(fieldName) - .dataType(SchemaFieldObjectType.fromTypeList(ARRAY, MapperUtil.getSimpleType(items, specFile))) - .build(); + .builder() + .baseName(fieldName) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.ARRAY, MapperUtil.getSimpleType(items, specFile))) + .build(); fieldObjectArrayList.add(field); addPropertiesToFieldObject(field, schema); } @@ -452,9 +424,61 @@ private static List processArray( return fieldObjectArrayList; } - private static List processAdditionalProperties( + private static List processObject( final String fieldName, final String className, final Schema schema, final SpecFile specFile, final Map totalSchemas, final Map compositedSchemas, final List antiLoopList) { + final List fieldObjectArrayList = new LinkedList<>(); + + if (ObjectUtils.allNull(className, fieldName)) { + schema.getProperties().forEach( + processProperties(totalSchemas, compositedSchemas, fieldObjectArrayList, specFile, schema, antiLoopList)); + } else if (antiLoopList.contains(className)) { + fieldObjectArrayList + .add(SchemaFieldObject + .builder() + .baseName(className) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.OBJECT, MapperUtil.getPojoName(className, specFile))) + .build()); + } else if (antiLoopList.contains(fieldName)) { + fieldObjectArrayList + .add(SchemaFieldObject + .builder() + .baseName(fieldName) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.OBJECT, MapperUtil.getPojoName(fieldName, specFile))) + .build()); + } else { + final String name = StringUtils.defaultIfBlank(className, fieldName); + compositedSchemas.putAll( + mapComponentToSchemaObject(totalSchemas, compositedSchemas, antiLoopList, schema, name, specFile, + specFile.getModelPackage())); + fieldObjectArrayList + .add(SchemaFieldObject + .builder() + .baseName(name) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.OBJECT, MapperUtil.getPojoName(name, specFile))) + .build()); + } + + return fieldObjectArrayList; + } + + private static List processMap( + final String fieldName, final Schema schema, final SpecFile specFile, final Map totalSchemas, final Map compositedSchemas, + final List antiLoopList) { + final var fieldObjectArrayList = new ArrayList(); + + if (TypeConstants.OBJECT.equalsIgnoreCase(schema.getType())) { + schema.getProperties().forEach(processProperties(totalSchemas, compositedSchemas, fieldObjectArrayList, specFile, schema, antiLoopList)); + } + + if (Objects.nonNull(schema.getAdditionalProperties())) { + fieldObjectArrayList.addAll(processAdditionalProperties(fieldName, schema, specFile)); + } + + return fieldObjectArrayList; + } + + private static List processAdditionalProperties(final String fieldName, final Schema schema, final SpecFile specFile) { final var fieldObjectArrayList = new ArrayList(); final Object addPropObj = schema.getAdditionalProperties(); @@ -463,8 +487,7 @@ private static List processAdditionalProperties( .add(SchemaFieldObject .builder() .baseName(fieldName) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(MAP, OBJECT)) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, TypeConstants.OBJECT)) .build()); } else { final Schema additionalProperties = (Schema) schema.getAdditionalProperties(); @@ -472,8 +495,7 @@ private static List processAdditionalProperties( final String refSchemaName = getRef(additionalProperties, specFile); final var field = SchemaFieldObject.builder() .baseName(fieldName) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(MAP, refSchemaName)) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, refSchemaName)) .build(); setFieldType(field, schema, additionalProperties, specFile, refSchemaName); fieldObjectArrayList.add(field); @@ -482,8 +504,7 @@ private static List processAdditionalProperties( .add(SchemaFieldObject .builder() .baseName("additionalProperties") - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(MAP, ARRAY, MapperUtil.getSimpleType(additionalProperties.getItems(), specFile))) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, TypeConstants.ARRAY, MapperUtil.getSimpleType(additionalProperties.getItems(), specFile))) .build()); } else { final String type = isBasicType(additionalProperties) ? MapperUtil.getSimpleType(additionalProperties, specFile) @@ -492,8 +513,7 @@ private static List processAdditionalProperties( .add(SchemaFieldObject .builder() .baseName(fieldName) - .restrictionProperties(new SchemaFieldObjectProperties()) - .dataType(SchemaFieldObjectType.fromTypeList(MAP, type)) + .dataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, type)) .build()); } } @@ -535,26 +555,26 @@ private static SchemaObject createComposedSchema( private static void setFieldType(final SchemaFieldObject field, final Schema value, final Schema schema, final SpecFile specFile, final String key) { field.setRequired(Objects.nonNull(schema.getRequired()) && schema.getRequired().contains(key)); - if (Objects.nonNull(value.getType()) && ARRAY.equalsIgnoreCase(value.getType())) { + if (Objects.nonNull(value.getType()) && TypeConstants.ARRAY.equalsIgnoreCase(value.getType())) { final String typeArray; if (Objects.nonNull(value.getItems())) { typeArray = MapperUtil.getTypeArray((ArraySchema) value, specFile); } else { - typeArray = OBJECT; + typeArray = TypeConstants.OBJECT; } - field.setDataType(SchemaFieldObjectType.fromTypeList(ARRAY, typeArray)); + field.setDataType(SchemaFieldObjectType.fromTypeList(TypeConstants.ARRAY, typeArray)); field.setImportClass(getImportClass(typeArray)); } else if (value instanceof MapSchema) { if (Objects.nonNull(value.getAdditionalProperties())) { final String typeObject = getMapTypeObject(value, specFile); - field.setDataType(SchemaFieldObjectType.fromTypeList(MAP, typeObject)); + field.setDataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, typeObject)); field.setImportClass(getImportClass(typeObject)); } else { final var typeMap = MapperUtil.getTypeMap((MapSchema) value, specFile); - field.setDataType(SchemaFieldObjectType.fromTypeList(MAP, typeMap)); + field.setDataType(SchemaFieldObjectType.fromTypeList(TypeConstants.MAP, typeMap)); field.setImportClass(getImportClass(typeMap)); } - } else if (Objects.nonNull(value.getType()) && OBJECT.equalsIgnoreCase(value.getType())) { + } else if (Objects.nonNull(value.getType()) && TypeConstants.OBJECT.equalsIgnoreCase(value.getType())) { var typeObject = ""; if (StringUtils.isNotBlank(value.get$ref())) { typeObject = getRef(schema, specFile); @@ -565,22 +585,23 @@ private static void setFieldType(final SchemaFieldObject field, final Schema } private static String getMapTypeObject(final Schema schema, final SpecFile specFile) { - String type = OBJECT; + final String type; if (schema.getAdditionalProperties() instanceof Boolean) { - type = OBJECT; + type = TypeConstants.OBJECT; } else { final Schema additionalProperties = (Schema) schema.getAdditionalProperties(); if (StringUtils.isNotBlank(additionalProperties.get$ref())) { type = getRef(additionalProperties, specFile); - } else if (StringUtils.isNotBlank(additionalProperties.getType()) && !additionalProperties.getType().equalsIgnoreCase(OBJECT)) { + } else if (StringUtils.isNotBlank(additionalProperties.getType()) && !additionalProperties.getType().equalsIgnoreCase(TypeConstants.OBJECT)) { final var additionalPropertiesField = SchemaFieldObject .builder() - .restrictionProperties(new SchemaFieldObjectProperties()) .baseName(additionalProperties.getName()) .dataType(new SchemaFieldObjectType(MapperUtil.getSimpleType(additionalProperties, specFile))) .build(); setFieldType(additionalPropertiesField, additionalProperties, additionalProperties, specFile, ""); type = getMapFieldType(additionalPropertiesField); + } else { + type = TypeConstants.OBJECT; } } @@ -591,16 +612,16 @@ private static String getMapFieldType(final SchemaFieldObject schemaFieldObject) final String fieldType = schemaFieldObject.getDataType().toString(); final String type; switch (fieldType) { - case BIG_DECIMAL: - case INTEGER: - case DOUBLE: - case FLOAT: - case LONG: - case STRING: + case TypeConstants.BIG_DECIMAL: + case TypeConstants.INTEGER: + case TypeConstants.DOUBLE: + case TypeConstants.FLOAT: + case TypeConstants.LONG: + case TypeConstants.STRING: type = fieldType; break; default: - type = OBJECT; + type = TypeConstants.OBJECT; break; } @@ -622,9 +643,8 @@ private static void processEnumField( final String key, final Schema value, final SpecFile specFile, final List fieldObjectArrayList, final List enumValues, final Schema schema) { final var field = SchemaFieldObject .builder() - .restrictionProperties(new SchemaFieldObjectProperties()) .baseName(key) - .dataType(new SchemaFieldObjectType(ENUM)) + .dataType(new SchemaFieldObjectType(TypeConstants.ENUM)) .build(); field.setRequired(Objects.nonNull(schema.getRequired()) && schema.getRequired().contains(key)); final var dataType = MapperUtil.getSimpleType(value, specFile); @@ -637,22 +657,22 @@ private static void processEnumField( valueName = valueName.replace(".", "_DOT_"); switch (dataType) { - case INTEGER: + case TypeConstants.INTEGER: enumValuesMap.put("INTEGER_" + valueName, enumValue.toString()); break; - case LONG: + case TypeConstants.LONG: enumValuesMap.put("LONG_" + valueName, enumValue + "l"); break; - case DOUBLE: + case TypeConstants.DOUBLE: enumValuesMap.put("DOUBLE_" + valueName, enumValue.toString()); break; - case FLOAT: + case TypeConstants.FLOAT: enumValuesMap.put("FLOAT_" + valueName, enumValue + "f"); break; - case BIG_DECIMAL: + case TypeConstants.BIG_DECIMAL: enumValuesMap.put("BIG_DECIMAL_" + valueName, "new BigDecimal(\"" + enumValue + "\")"); break; - case STRING: + case TypeConstants.STRING: default: enumValuesMap.put(StringUtils.upperCase(valueName), '"' + enumValue.toString() + '"'); break; @@ -668,7 +688,39 @@ private static void processEnumField( } private static String getImportClass(final String type) { - return StringUtils.isNotBlank(type) && !BASIC_TYPES.contains(type) ? type : ""; + return StringUtils.isNotBlank(type) && !TypeConstants.NO_IMPORT_TYPE.contains(type) ? StringUtils.capitalize(type) : ""; + } + + private static String getDateType(final SpecFile specFile) { + final String dateType; + switch (specFile.getUseTimeType()) { + case ZONED: + dateType = TypeConstants.ZONEDDATE; + break; + case OFFSET: + dateType = TypeConstants.OFFSETDATE; + break; + default: + dateType = TypeConstants.LOCALDATE; + } + + return dateType; + } + + private static String getDateTimeType(final SpecFile specFile) { + final String dateTimeType; + switch (specFile.getUseTimeType()) { + case ZONED: + dateTimeType = TypeConstants.ZONEDDATETIME; + break; + case OFFSET: + dateTimeType = TypeConstants.OFFSETDATETIME; + break; + default: + dateTimeType = TypeConstants.LOCALDATETIME; + } + + return dateTimeType; } } diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperPathUtil.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperPathUtil.java index 24042ea5..e87602ef 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperPathUtil.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperPathUtil.java @@ -16,7 +16,6 @@ import com.sngular.api.generator.plugin.openapi.exception.DuplicatedOperationException; import com.sngular.api.generator.plugin.openapi.model.AuthSchemaObject; -import com.sngular.api.generator.plugin.openapi.model.BasicTypeConstants; import com.sngular.api.generator.plugin.openapi.model.ContentObject; import com.sngular.api.generator.plugin.openapi.model.GlobalObject; import com.sngular.api.generator.plugin.openapi.model.OperationObject; @@ -24,6 +23,7 @@ import com.sngular.api.generator.plugin.openapi.model.PathObject; import com.sngular.api.generator.plugin.openapi.model.RequestObject; import com.sngular.api.generator.plugin.openapi.model.ResponseObject; +import com.sngular.api.generator.plugin.openapi.model.TypeConstants; import com.sngular.api.generator.plugin.openapi.parameter.SpecFile; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; @@ -43,12 +43,6 @@ public class MapperPathUtil { - public static final String ARRAY = "array"; - - public static final String MAP = "map"; - - public static final String OBJECT = "object"; - public static final String INLINE_PARAMETER = "InlineParameter"; private MapperPathUtil() {} @@ -84,7 +78,7 @@ private static HashMap getMapComponentsTypes(final Components co components.getSchemas().forEach((key, value) -> { if (!mapComponents.containsKey(key)) { final var type = checkSchemaType(value, specFile); - mapComponents.put(key, OBJECT.equalsIgnoreCase(type) ? MapperUtil.getPojoName(key, specFile) : type); + mapComponents.put(key, TypeConstants.OBJECT.equalsIgnoreCase(type) ? MapperUtil.getPojoName(key, specFile) : type); } }); } @@ -98,16 +92,16 @@ private static String checkSchemaType(final Schema schema, final SpecFile spe dataType = "array-" + MapperUtil.getTypeArray((ArraySchema) schema, specFile); } else if (schema instanceof MapSchema) { if (schema.getAdditionalProperties() != null) { - dataType = OBJECT; + dataType = TypeConstants.OBJECT; } else { dataType = "map-" + MapperUtil.getTypeMap((MapSchema) schema, specFile); } - } else if (OBJECT.equals(schema.getType()) && StringUtils.isNotBlank(schema.get$ref())) { + } else if (TypeConstants.OBJECT.equals(schema.getType()) && StringUtils.isNotBlank(schema.get$ref())) { final String[] pathObjectRef = schema.get$ref().split("/"); dataType = MapperUtil.getPojoName(pathObjectRef[pathObjectRef.length - 1], specFile); } else if (!Objects.nonNull(schema.getType()) && Boolean.TRUE.equals(checkSchemaCombinator(schema))) { - dataType = OBJECT; + dataType = TypeConstants.OBJECT; } else { dataType = schema.getType(); } @@ -246,7 +240,7 @@ private static List mapParameterObjects( .description(refParameter.getDescription()) .in(refParameter.getDescription()) .className(MapperUtil.getSimpleType(refParameter.getSchema(), specFile)) - .isCollection(ARRAY.equalsIgnoreCase(refParameter.getSchema().getType())) + .isCollection(TypeConstants.ARRAY.equalsIgnoreCase(refParameter.getSchema().getType())) .build()); } else if (Objects.nonNull(parameter.getContent())) { addInlineParametersToList(contentClassName, parameterObjects, parameter, specFile, globalObject); @@ -257,7 +251,7 @@ private static List mapParameterObjects( .description(parameter.getDescription()) .in(parameter.getIn()) .className(MapperUtil.getSimpleType(parameter.getSchema(), specFile)) - .isCollection(ARRAY.equalsIgnoreCase(parameter.getSchema().getType())) + .isCollection(TypeConstants.ARRAY.equalsIgnoreCase(parameter.getSchema().getType())) .build()); } } @@ -272,7 +266,7 @@ private static void addInlineParametersToList( for (Entry contentEntrySet : content.entrySet()) { final String inlineParameter = getPojoName(INLINE_PARAMETER + StringUtils.capitalize(contentClassName) + StringUtils.capitalize(parameter.getName()), specFile); - if (OBJECT.equalsIgnoreCase(contentEntrySet.getValue().getSchema().getType())) { + if (TypeConstants.OBJECT.equalsIgnoreCase(contentEntrySet.getValue().getSchema().getType())) { parameterObjects.add(ParameterObject.builder() .name(parameter.getName()) .required(parameter.getRequired()) @@ -322,7 +316,7 @@ private static List mapContentObject(final SpecFile specFile, fin .refName(pojoName) .build()); } else if (Objects.nonNull(mediaTypeEntry.getValue().getSchema().getType()) - && BasicTypeConstants.BASIC_OBJECT_TYPE.contains(mediaTypeEntry.getValue().getSchema().getType())) { + && TypeConstants.BASIC_OBJECT_TYPE.contains(mediaTypeEntry.getValue().getSchema().getType())) { contentObjects.add(ContentObject.builder() .typeData(mapDataType(mediaTypeEntry.getValue().getSchema(), globalObject.getComponentsTypeMap())) .name(mediaTypeEntry.getKey()) @@ -332,7 +326,7 @@ private static List mapContentObject(final SpecFile specFile, fin } else if (Boolean.TRUE.equals(checkSchemaCombinator(mediaTypeEntry.getValue().getSchema()))) { final var composedSchemaPojoName = preparePojoNameForComposedSchema(inlineObject, mediaTypeEntry.getValue().getSchema(), specFile); contentObjects.add(ContentObject.builder() - .typeData(OBJECT) + .typeData(TypeConstants.OBJECT) .name(mediaTypeEntry.getKey()) .importName(StringUtils.capitalize( mapRefName(mediaTypeEntry.getValue().getSchema(), globalObject.getComponentsTypeMap(), composedSchemaPojoName))) @@ -351,7 +345,7 @@ private static List mapContentObject(final SpecFile specFile, fin return contentObjects; } - private static String preparePojoNameForComposedSchema(final String inlineObject, final Schema schema, final SpecFile specFile) { + private static String preparePojoNameForComposedSchema(final String inlineObject, final Schema schema, final SpecFile specFile) { String composedSchemaPojoName = ""; if (Objects.nonNull(schema.getAllOf())) { composedSchemaPojoName = getPojoName(inlineObject + "AllOf", specFile); @@ -367,25 +361,25 @@ private static String defineTypeName(final Schema schema, final GlobalObject final String typeName; if (Objects.nonNull(schema.getType())) { switch (schema.getType()) { - case BasicTypeConstants.INTEGER: + case TypeConstants.INTEGER: typeName = getIntegerFormat(schema); break; - case BasicTypeConstants.NUMBER: + case TypeConstants.NUMBER: typeName = getNumberFormat(schema); break; - case BasicTypeConstants.BOOLEAN: - typeName = "Boolean"; + case TypeConstants.BOOLEAN: + typeName = TypeConstants.BOOLEAN; break; - case ARRAY: + case TypeConstants.ARRAY: final ArraySchema arraySchema = (ArraySchema) schema; typeName = getListName(globalObject, pojoName, arraySchema); break; - case OBJECT: + case TypeConstants.OBJECT: typeName = pojoName; break; - case BasicTypeConstants.STRING: + case TypeConstants.STRING: default: - typeName = "String"; + typeName = TypeConstants.STRING; break; } } else { @@ -406,22 +400,22 @@ private static String getListName(final GlobalObject globalObject, final String private static String getIntegerFormat(final Schema schema) { String typeName = ""; - if ("int32".equalsIgnoreCase(schema.getFormat()) || !Objects.nonNull(schema.getFormat())) { - typeName = "Integer"; - } else if ("int64".equalsIgnoreCase(schema.getFormat())) { - typeName = "Long"; + if (TypeConstants.INT_32.equalsIgnoreCase(schema.getFormat()) || !Objects.nonNull(schema.getFormat())) { + typeName = TypeConstants.INTEGER; + } else if (TypeConstants.INT_64.equalsIgnoreCase(schema.getFormat())) { + typeName = TypeConstants.LONG; } return typeName; } private static String getNumberFormat(final Schema schema) { String typeName = ""; - if ("float".equalsIgnoreCase(schema.getFormat())) { - typeName = "Float"; - } else if ("double".equalsIgnoreCase(schema.getFormat())) { - typeName = "Double"; + if (TypeConstants.FLOAT.equalsIgnoreCase(schema.getFormat())) { + typeName = TypeConstants.FLOAT; + } else if (TypeConstants.DOUBLE.equalsIgnoreCase(schema.getFormat())) { + typeName = TypeConstants.DOUBLE; } else if (schema.getFormat().isEmpty()) { - typeName = "Integer"; + typeName = TypeConstants.INTEGER; } return typeName; } @@ -437,18 +431,19 @@ private static String getSchemaType(final Schema schema, final Map schema, final Map componentsTypes, final String pojoName) { var refSchema = ""; - if (ARRAY.equalsIgnoreCase(schema.getType())) { + if (TypeConstants.ARRAY.equalsIgnoreCase(schema.getType())) { final ArraySchema arraySchema = (ArraySchema) schema; - if (OBJECT.equalsIgnoreCase(schema.getItems().getType())) { + if (TypeConstants.OBJECT.equalsIgnoreCase(schema.getItems().getType())) { refSchema = pojoName; - } else if (ARRAY.equalsIgnoreCase(schema.getItems().getType())) { + } else if (TypeConstants.ARRAY.equalsIgnoreCase(schema.getItems().getType())) { refSchema = mapRefName(schema.getItems(), componentsTypes, pojoName); } else { refSchema = StringUtils.isNotBlank(arraySchema.getItems().get$ref()) ? getRefSchema(arraySchema.getItems().get$ref(), componentsTypes) : null; diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperUtil.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperUtil.java index bb683365..6eb05903 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperUtil.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/openapi/utils/MapperUtil.java @@ -8,6 +8,7 @@ import java.util.Objects; +import com.sngular.api.generator.plugin.openapi.model.TypeConstants; import com.sngular.api.generator.plugin.openapi.parameter.SpecFile; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.IntegerSchema; @@ -19,69 +20,49 @@ public class MapperUtil { - public static final String INTEGER = "integer"; - - public static final String DOUBLE = "double"; - - public static final String FLOAT = "float"; - - public static final String NUMBER = "number"; - - public static final String INT_32 = "int32"; - - public static final String INT_64 = "int64"; - - public static final String LONG = "long"; - - public static final String BIG_DECIMAL = "bigDecimal"; - - public static final String STRING = "String"; - - public static final String OBJECT = "Object"; - private MapperUtil() {} public static String getSimpleType(final Schema schema, final SpecFile specFile) { final String type; - if (NUMBER.equalsIgnoreCase(schema.getType())) { - if (FLOAT.equalsIgnoreCase(schema.getFormat())) { - type = FLOAT; - } else if (DOUBLE.equalsIgnoreCase(schema.getFormat())) { - type = DOUBLE; + if (TypeConstants.NUMBER.equalsIgnoreCase(schema.getType())) { + if (TypeConstants.FLOAT.equalsIgnoreCase(schema.getFormat())) { + type = TypeConstants.FLOAT; + } else if (TypeConstants.DOUBLE.equalsIgnoreCase(schema.getFormat())) { + type = TypeConstants.DOUBLE; } else { - type = BIG_DECIMAL; + type = TypeConstants.BIG_DECIMAL; } - } else if (INTEGER.equalsIgnoreCase(schema.getType())) { - if (INT_64.equalsIgnoreCase(schema.getFormat())) { - type = LONG; + } else if (TypeConstants.INTEGER.equalsIgnoreCase(schema.getType())) { + if (TypeConstants.INT_64.equalsIgnoreCase(schema.getFormat())) { + type = TypeConstants.LONG; } else { - type = INTEGER; + type = TypeConstants.INTEGER; } } else if (Objects.nonNull(schema.get$ref())) { final String[] pathObjectRef = schema.get$ref().split("/"); type = getPojoName(pathObjectRef[pathObjectRef.length - 1], specFile); - } else if (INT_32.equalsIgnoreCase(schema.getType()) || INT_64.equalsIgnoreCase(schema.getType())) { - type = INTEGER; + } else if (TypeConstants.INT_32.equalsIgnoreCase(schema.getType()) || TypeConstants.INT_64.equalsIgnoreCase(schema.getType())) { + type = TypeConstants.INTEGER; } else if (schema instanceof ArraySchema) { - type = MapperPathUtil.ARRAY; + type = TypeConstants.ARRAY; } else { - type = ObjectUtils.defaultIfNull(StringUtils.capitalize(schema.getType()), OBJECT); + type = ObjectUtils.defaultIfNull(schema.getType(), TypeConstants.OBJECT); } - return StringUtils.capitalize(type); + return type; } public static String getSimpleType(final Object schema) { final String type; if (schema instanceof Boolean) { - type = OBJECT; + type = TypeConstants.OBJECT; } else if (schema instanceof Integer) { - type = INTEGER; + type = TypeConstants.INTEGER; } else if (schema instanceof Float) { - type = FLOAT; + type = TypeConstants.FLOAT; } else if (schema instanceof Double) { - type = DOUBLE; + type = TypeConstants.DOUBLE; } else { - type = STRING; + type = TypeConstants.STRING; } return type; } @@ -89,9 +70,9 @@ public static String getSimpleType(final Object schema) { public static String getTypeMap(final MapSchema mapSchema, final SpecFile specFile) { var typeMap = ""; if (mapSchema.getAdditionalProperties() instanceof StringSchema) { - typeMap = STRING; + typeMap = TypeConstants.STRING; } else if (mapSchema.getAdditionalProperties() instanceof IntegerSchema) { - typeMap = "Integer"; + typeMap = TypeConstants.INTEGER; } else { final Schema schema = (Schema) mapSchema.getAdditionalProperties(); if (StringUtils.isNotBlank(schema.get$ref())) { @@ -105,9 +86,9 @@ public static String getTypeMap(final MapSchema mapSchema, final SpecFile specFi public static String getTypeArray(final ArraySchema array, final SpecFile specFile) { var typeArray = ""; if (array.getItems() instanceof StringSchema) { - typeArray = STRING; + typeArray = TypeConstants.STRING; } else if (array.getItems() instanceof IntegerSchema) { - typeArray = "Integer"; + typeArray = TypeConstants.INTEGER; } else if (StringUtils.isNotBlank(array.getItems().get$ref())) { final String[] pathObjectRef = array.getItems().get$ref().split("/"); typeArray = getPojoName(pathObjectRef[pathObjectRef.length - 1], specFile); diff --git a/multiapi-engine/src/main/resources/templates/openapi/templateSchema.ftlh b/multiapi-engine/src/main/resources/templates/openapi/templateSchema.ftlh index 8d2833d7..26cf6119 100644 --- a/multiapi-engine/src/main/resources/templates/openapi/templateSchema.ftlh +++ b/multiapi-engine/src/main/resources/templates/openapi/templateSchema.ftlh @@ -119,19 +119,19 @@ public class ${schema.className} { <#if field.required?has_content && field.required == true> @NotNull - <#if field.dataType.baseType == "Array"> + <#if field.dataType.baseType == "array"> <#if field.required> private final ${field.dataType} ${field.baseName?uncap_first}; <#else> private ${field.dataType} ${field.baseName?uncap_first} = new ${field.dataType?api.getImplementationTypeString()}(); - <#elseif field.dataType.baseType == "Map"> + <#elseif field.dataType.baseType == "map"> <#if field.required> private final ${field.dataType} ${field.baseName?uncap_first}; <#else> private ${field.dataType} ${field.baseName?uncap_first} = new ${field.dataType?api.getImplementationTypeString()}(); - <#elseif field.dataType.baseType == "Enum"> + <#elseif field.dataType.baseType == "enum"> <#if field.required> private final ${field.baseName?cap_first} ${field.baseName?uncap_first}; <#else> @@ -158,7 +158,7 @@ public class ${schema.className} { return String.valueOf(value); } } - <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "Object"> + <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "object"> <#if field.required> private final ${field.dataType.innerType?cap_first} ${field.baseName?uncap_first}; <#else> @@ -174,7 +174,7 @@ public class ${schema.className} { private ${schema.className}(<@compress single_line=true><#list schema.fieldObjectList as field> - <#if field.dataType.baseType == "Enum">${field.baseName?cap_first} ${field.baseName?uncap_first}<#elseif field.dataType.baseType == "Array">${field.dataType} ${field.baseName?uncap_first}<#elseif field.dataType.baseType == "Map">${field.dataType} ${field.baseName?uncap_first}<#elseif field.dataType.innerType?has_content && field.dataType.baseType == "Object">${field.dataType.innerType?cap_first} ${field.baseName?uncap_first}<#else>${field.dataType?cap_first} ${field.baseName?uncap_first}<#sep>, ) { + <#if field.dataType.baseType == "enum">${field.baseName?cap_first} ${field.baseName?uncap_first}<#elseif field.dataType.baseType == "array">${field.dataType} ${field.baseName?uncap_first}<#elseif field.dataType.baseType == "map">${field.dataType} ${field.baseName?uncap_first}<#elseif field.dataType.innerType?has_content && field.dataType.baseType == "object">${field.dataType.innerType?cap_first} ${field.baseName?uncap_first}<#else>${field.dataType?cap_first} ${field.baseName?uncap_first}<#sep>, ) { <#list schema.fieldObjectList as field> this.${field.baseName?uncap_first} = ${field.baseName?uncap_first}; @@ -214,20 +214,20 @@ public class ${schema.className} { public static class ${schema.className}Builder { <#list schema.fieldObjectList as field> - <#if field.dataType.baseType == "Array"> + <#if field.dataType.baseType == "array"> private ${field.dataType} ${field.baseName?uncap_first} = new ${field.dataType?api.getImplementationTypeString()}(); - <#elseif field.dataType.baseType == "Map"> + <#elseif field.dataType.baseType == "map"> private ${field.dataType} ${field.baseName?uncap_first} = new ${field.dataType?api.getImplementationTypeString()}(); - <#elseif field.dataType.baseType == "Enum"> + <#elseif field.dataType.baseType == "enum"> private ${field.baseName?cap_first} ${field.baseName?uncap_first}; - <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "Object"> + <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "object"> private ${field.dataType.innerType?cap_first} ${field.baseName?uncap_first}; <#else> private ${field.dataType?cap_first} ${field.baseName?uncap_first}; <#list schema.fieldObjectList as field> - <#if field.dataType.baseType == "Array"> + <#if field.dataType.baseType == "array"> public ${schema.className}.${schema.className}Builder ${field.baseName?uncap_first}(${field.dataType} ${field.baseName?uncap_first}) { if (!${field.baseName?uncap_first}.isEmpty()) { this.${field.baseName?uncap_first}.addAll(${field.baseName?uncap_first}); @@ -241,7 +241,7 @@ public class ${schema.className} { } return this; } - <#elseif field.dataType.baseType == "Map"> + <#elseif field.dataType.baseType == "map"> public ${schema.className}.${schema.className}Builder ${field.baseName?uncap_first}(${field.dataType} ${field.baseName?uncap_first}) { this.${field.baseName?uncap_first} = ${field.baseName?uncap_first}; return this; @@ -251,12 +251,12 @@ public class ${schema.className} { this.${field.baseName?uncap_first}.put(key, value); return this; } - <#elseif field.dataType.baseType == "Enum"> + <#elseif field.dataType.baseType == "enum"> public ${schema.className}.${schema.className}Builder ${field.baseName?uncap_first}(${field.baseName?cap_first} ${field.baseName}) { this.${field.baseName?uncap_first} = ${field.baseName?uncap_first}; return this; } - <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "Object"> + <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "object"> public ${schema.className}.${schema.className}Builder ${field.baseName?uncap_first}(${field.dataType.innerType?cap_first} ${field.baseName?uncap_first}) { this.${field.baseName?uncap_first} = ${field.baseName?uncap_first}; return this; @@ -282,7 +282,7 @@ public class ${schema.className} { * @return ${field.baseName?uncap_first} */ @Schema(name = "${field.baseName?uncap_first}", required = <#if field.required?has_content && field.required == true>true<#else>false) - <#if field.dataType.baseType == "Array"> + <#if field.dataType.baseType == "array"> public ${field.dataType} get${field.baseName?cap_first}() { return ${field.baseName?uncap_first}; } @@ -291,7 +291,7 @@ public class ${schema.className} { this.${field.baseName?uncap_first} = ${field.baseName?uncap_first}; } - <#elseif field.dataType.baseType == "Map"> + <#elseif field.dataType.baseType == "map"> public ${field.dataType} get${field.baseName?cap_first}() { return ${field.baseName?uncap_first}; } @@ -300,7 +300,7 @@ public class ${schema.className} { this.${field.baseName?uncap_first} = ${field.baseName?uncap_first}; } - <#elseif field.dataType.baseType == "Enum"> + <#elseif field.dataType.baseType == "enum"> public ${field.baseName?cap_first} get${field.baseName?cap_first}() { return ${field.baseName?uncap_first}; } @@ -309,7 +309,7 @@ public class ${schema.className} { this.${field.baseName?uncap_first} = ${field.baseName?uncap_first}; } - <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "Object"> + <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "object"> public ${field.dataType.innerType?cap_first} get${field.baseName?cap_first}() { return ${field.baseName?uncap_first}; } diff --git a/multiapi-engine/src/main/resources/templates/openapi/templateSchemaWithLombok.ftlh b/multiapi-engine/src/main/resources/templates/openapi/templateSchemaWithLombok.ftlh index 00904a55..735e3c13 100644 --- a/multiapi-engine/src/main/resources/templates/openapi/templateSchemaWithLombok.ftlh +++ b/multiapi-engine/src/main/resources/templates/openapi/templateSchemaWithLombok.ftlh @@ -5,7 +5,7 @@ import java.util.Objects; import com.fasterxml.jackson.annotation.JsonProperty; <#list schema.fieldObjectList as field> - <#if field.dataType.baseType == "Enum"> + <#if field.dataType.baseType == "enum"> import com.fasterxml.jackson.annotation.JsonValue; <#break> @@ -115,11 +115,11 @@ public class ${schema.className} { <#if field.required?has_content && field.required == true> @NonNull - <#if field.dataType.baseType == "Array"> + <#if field.dataType.baseType == "array"> private ${field.dataType} ${field.baseName?uncap_first} = new ${field.dataType?api.getImplementationTypeString()}(); - <#elseif field.dataType.baseType == "Map"> + <#elseif field.dataType.baseType == "map"> private ${field.dataType} ${field.baseName?uncap_first} = new ${field.dataType?api.getImplementationTypeString()}(); - <#elseif field.dataType.baseType == "Enum"> + <#elseif field.dataType.baseType == "enum"> private ${field.baseName?cap_first} ${field.baseName?uncap_first}; public enum ${field.baseName?cap_first} { @@ -143,7 +143,7 @@ public class ${schema.className} { return String.valueOf(value); } } - <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "Object"> + <#elseif field.dataType.innerType?has_content && field.dataType.baseType == "object"> private ${field.dataType.innerType?cap_first} ${field.baseName?uncap_first}; <#else> private ${field.dataType?cap_first} ${field.baseName?uncap_first}; @@ -154,7 +154,7 @@ public class ${schema.className} { @Builder @Jacksonized private ${schema.className}(<@compress single_line=true><#list schema.fieldObjectList as field> - <#if field.required>@NonNull <#if field.dataType.baseType == "Enum">${field.baseName?cap_first} ${field.baseName?uncap_first}<#elseif field.dataType.baseType == "Array">${field.dataType} ${field.baseName?uncap_first}<#elseif field.dataType.baseType == "Map">${field.dataType} ${field.baseName?uncap_first}<#elseif field.dataType.innerType?has_content && field.dataType.baseType == "Object">${field.dataType.innerType?cap_first} ${field.baseName?uncap_first}<#else>${field.dataType?cap_first} ${field.baseName?uncap_first}<#sep>, ) { + <#if field.required>@NonNull <#if field.dataType.baseType == "enum">${field.baseName?cap_first} ${field.baseName?uncap_first}<#elseif field.dataType.baseType == "array">${field.dataType} ${field.baseName?uncap_first}<#elseif field.dataType.baseType == "map">${field.dataType} ${field.baseName?uncap_first}<#elseif field.dataType.innerType?has_content && field.dataType.baseType == "object">${field.dataType.innerType?cap_first} ${field.baseName?uncap_first}<#else>${field.dataType?cap_first} ${field.baseName?uncap_first}<#sep>, ) { <#list schema.fieldObjectList as field> this.${field.baseName?uncap_first} = ${field.baseName?uncap_first}; 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 fb1c1222..0f466330 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 @@ -15,6 +15,7 @@ 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.SpecFile; import com.sngular.api.generator.test.utils.TestUtils; import org.apache.commons.collections4.CollectionUtils; @@ -351,6 +352,44 @@ public final class OpenApiGeneratorFixtures { .build() ); + static final List TEST_DATE_TIME = List.of( + SpecFile + .builder() + .filePath("openapigenerator/testDateTime/api-test.yml") + .apiPackage("com.sngular.multifileplugin.testDateTime") + .modelPackage("com.sngular.multifileplugin.testDateTime.model") + .clientPackage("com.sngular.multifileplugin.testDateTime.client") + .modelNameSuffix("DTO") + .useLombokModelAnnotation(true) + .build() + ); + + static final List TEST_DATE_TIME_ZONED = List.of( + SpecFile + .builder() + .filePath("openapigenerator/testDateTimeZoned/api-test.yml") + .apiPackage("com.sngular.multifileplugin.testDateTimeZoned") + .modelPackage("com.sngular.multifileplugin.testDateTimeZoned.model") + .clientPackage("com.sngular.multifileplugin.testDateTimeZoned.client") + .modelNameSuffix("DTO") + .useLombokModelAnnotation(true) + .useTimeType(TimeType.ZONED) + .build() + ); + + static final List TEST_DATE_TIME_OFFSET = List.of( + SpecFile + .builder() + .filePath("openapigenerator/testDateTimeOffset/api-test.yml") + .apiPackage("com.sngular.multifileplugin.testDateTimeOffset") + .modelPackage("com.sngular.multifileplugin.testDateTimeOffset.model") + .clientPackage("com.sngular.multifileplugin.testDateTimeOffset.client") + .modelNameSuffix("DTO") + .useLombokModelAnnotation(true) + .useTimeType(TimeType.OFFSET) + .build() + ); + static Function validateOneOfInResponse() { final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testoneofinresponse"; @@ -1082,6 +1121,60 @@ static Function validateCreateDTO() { return (path) -> commonTest(path, expectedTestApiFile, expectedTestApiModelFiles, DEFAULT_TARGET_API, DEFAULT_MODEL_API, Collections.emptyList(), DEFAULT_EXCEPTION_API); } + static Function validateDateTime() { + final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testDateTime"; + + final String DEFAULT_MODEL_API = "generated/com/sngular/multifileplugin/testDateTime/model"; + + final String DEFAULT_EXCEPTION_API = "generated/com/sngular/multifileplugin/testDateTime/model/exception"; + + final List expectedTestApiFile = List.of( + "openapigenerator/testDateTime/assets/TestApi.java" + ); + + final List expectedTestApiModelFiles = List.of( + "openapigenerator/testDateTime/assets/model/TestDateDTO.java" + ); + + return (path) -> commonTest(path, expectedTestApiFile, expectedTestApiModelFiles, DEFAULT_TARGET_API, DEFAULT_MODEL_API, Collections.emptyList(), DEFAULT_EXCEPTION_API); + } + + static Function validateDateTimeZoned() { + final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testDateTimeZoned"; + + final String DEFAULT_MODEL_API = "generated/com/sngular/multifileplugin/testDateTimeZoned/model"; + + final String DEFAULT_EXCEPTION_API = "generated/com/sngular/multifileplugin/testDateTimeZoned/model/exception"; + + final List expectedTestApiFile = List.of( + "openapigenerator/testDateTimeZoned/assets/TestApi.java" + ); + + final List expectedTestApiModelFiles = List.of( + "openapigenerator/testDateTimeZoned/assets/model/TestDateDTO.java" + ); + + return (path) -> commonTest(path, expectedTestApiFile, expectedTestApiModelFiles, DEFAULT_TARGET_API, DEFAULT_MODEL_API, Collections.emptyList(), DEFAULT_EXCEPTION_API); + } + + static Function validateDateTimeOffset() { + final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testDateTimeOffset"; + + final String DEFAULT_MODEL_API = "generated/com/sngular/multifileplugin/testDateTimeOffset/model"; + + final String DEFAULT_EXCEPTION_API = "generated/com/sngular/multifileplugin/testDateTimeOffset/model/exception"; + + final List expectedTestApiFile = List.of( + "openapigenerator/testDateTimeOffset/assets/TestApi.java" + ); + + final List expectedTestApiModelFiles = List.of( + "openapigenerator/testDateTimeOffset/assets/model/TestDateDTO.java" + ); + + return (path) -> commonTest(path, expectedTestApiFile, expectedTestApiModelFiles, DEFAULT_TARGET_API, DEFAULT_MODEL_API, Collections.emptyList(), DEFAULT_EXCEPTION_API); + } + private static Boolean commonTest( final Path resultPath, final List expectedFile, final List expectedModelFiles, final String targetApi, final String targetModel, final List expectedExceptionFiles, final String targetException) { 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 d352df2f..be24632f 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 @@ -83,7 +83,13 @@ static Stream fileSpecToProcess() { Arguments.of("testValidationAnnotationsLombok", OpenApiGeneratorFixtures.TEST_VALIDATION_ANNOTATIONS_LOMBOK, OpenApiGeneratorFixtures.validateValidationAnnotationsLombok()), Arguments.of("testCreateDTO", OpenApiGeneratorFixtures.TEST_CREATE_DTO, - OpenApiGeneratorFixtures.validateCreateDTO()) + OpenApiGeneratorFixtures.validateCreateDTO()), + Arguments.of("testDateTime", OpenApiGeneratorFixtures.TEST_DATE_TIME, + OpenApiGeneratorFixtures.validateDateTime()), + Arguments.of("testDateTimeZoned", OpenApiGeneratorFixtures.TEST_DATE_TIME_ZONED, + OpenApiGeneratorFixtures.validateDateTimeZoned()), + Arguments.of("testDateTimeOffset", OpenApiGeneratorFixtures.TEST_DATE_TIME_OFFSET, + OpenApiGeneratorFixtures.validateDateTimeOffset()) ); } diff --git a/multiapi-engine/src/test/resources/openapigenerator/testComplexAnyOf/assets/ApiSchemaDTO.java b/multiapi-engine/src/test/resources/openapigenerator/testComplexAnyOf/assets/ApiSchemaDTO.java index 21e42de0..39c3c999 100644 --- a/multiapi-engine/src/test/resources/openapigenerator/testComplexAnyOf/assets/ApiSchemaDTO.java +++ b/multiapi-engine/src/test/resources/openapigenerator/testComplexAnyOf/assets/ApiSchemaDTO.java @@ -6,9 +6,9 @@ import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; +import com.sngular.multifileplugin.testcomplexanyof.model.ApiTypeArrayDTO; import java.util.List; import java.util.ArrayList; -import com.sngular.multifileplugin.testcomplexanyof.model.ApiTypeArrayDTO; import com.sngular.multifileplugin.testcomplexanyof.model.exception.ModelClassException; import com.sngular.multifileplugin.testcomplexanyof.model.customvalidator.NotNull; diff --git a/multiapi-engine/src/test/resources/openapigenerator/testComplexAnyOf/assets/ApiSequenceFieldDTO.java b/multiapi-engine/src/test/resources/openapigenerator/testComplexAnyOf/assets/ApiSequenceFieldDTO.java index 4efbbfe6..dc2b0189 100644 --- a/multiapi-engine/src/test/resources/openapigenerator/testComplexAnyOf/assets/ApiSequenceFieldDTO.java +++ b/multiapi-engine/src/test/resources/openapigenerator/testComplexAnyOf/assets/ApiSequenceFieldDTO.java @@ -7,9 +7,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.media.Schema; +import com.sngular.multifileplugin.testcomplexanyof.model.ApiTypeArrayDTO; import java.util.List; import java.util.ArrayList; -import com.sngular.multifileplugin.testcomplexanyof.model.ApiTypeArrayDTO; @JsonDeserialize(builder = ApiSequenceFieldDTO.ApiSequenceFieldDTOBuilder.class) public class ApiSequenceFieldDTO { diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTime/api-test.yml b/multiapi-engine/src/test/resources/openapigenerator/testDateTime/api-test.yml new file mode 100644 index 00000000..3d9e1813 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTime/api-test.yml @@ -0,0 +1,30 @@ +openapi: 3.0.2 +info: + title: Testing example file + version: 1.0.0 +servers: +- url: http://localhost/v1 +paths: + /test: + get: + tags: + - test + operationId: testDateTime + responses: + '200': + description: An object with date and date-time formats + content: + application/json: + schema: + $ref: '#/components/schemas/testDate' +components: + schemas: + testDate: + type: object + properties: + someDate: + type: string + format: date + someTime: + type: string + format: date-time diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTime/assets/TestApi.java b/multiapi-engine/src/test/resources/openapigenerator/testDateTime/assets/TestApi.java new file mode 100644 index 00000000..53f6f3e2 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTime/assets/TestApi.java @@ -0,0 +1,45 @@ +package com.sngular.multifileplugin.testDateTime; + +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.testDateTime.model.TestDateDTO; + +public interface TestApi { + + /** + * GET /test + * @return An object with date and date-time formats; (status code 200) + */ + + @Operation( + operationId = "testDateTime", + tags = {"test"}, + responses = { + @ApiResponse(responseCode = "200", description = "An object with date and date-time formats", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDateDTO.class))) + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = "/test", + produces = {"application/json"} + ) + + default ResponseEntity testDateTime() { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + +} diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTime/assets/model/TestDateDTO.java b/multiapi-engine/src/test/resources/openapigenerator/testDateTime/assets/model/TestDateDTO.java new file mode 100644 index 00000000..ac5b945c --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTime/assets/model/TestDateDTO.java @@ -0,0 +1,30 @@ +package com.sngular.multifileplugin.testDateTime.model; + +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +@Data +public class TestDateDTO { + + @JsonProperty(value ="someDate") + private LocalDate someDate; + + @JsonProperty(value ="someTime") + private LocalDateTime someTime; + + + @Builder + @Jacksonized + private TestDateDTO(LocalDate someDate, LocalDateTime someTime) { + this.someDate = someDate; + this.someTime = someTime; + + } + +} diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/api-test.yml b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/api-test.yml new file mode 100644 index 00000000..3d9e1813 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/api-test.yml @@ -0,0 +1,30 @@ +openapi: 3.0.2 +info: + title: Testing example file + version: 1.0.0 +servers: +- url: http://localhost/v1 +paths: + /test: + get: + tags: + - test + operationId: testDateTime + responses: + '200': + description: An object with date and date-time formats + content: + application/json: + schema: + $ref: '#/components/schemas/testDate' +components: + schemas: + testDate: + type: object + properties: + someDate: + type: string + format: date + someTime: + type: string + format: date-time diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/assets/TestApi.java b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/assets/TestApi.java new file mode 100644 index 00000000..53a6d10a --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/assets/TestApi.java @@ -0,0 +1,45 @@ +package com.sngular.multifileplugin.testDateTimeOffset; + +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.testDateTimeOffset.model.TestDateDTO; + +public interface TestApi { + + /** + * GET /test + * @return An object with date and date-time formats; (status code 200) + */ + + @Operation( + operationId = "testDateTime", + tags = {"test"}, + responses = { + @ApiResponse(responseCode = "200", description = "An object with date and date-time formats", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDateDTO.class))) + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = "/test", + produces = {"application/json"} + ) + + default ResponseEntity testDateTime() { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + +} diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/assets/model/TestDateDTO.java b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/assets/model/TestDateDTO.java new file mode 100644 index 00000000..3a6fc079 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeOffset/assets/model/TestDateDTO.java @@ -0,0 +1,29 @@ +package com.sngular.multifileplugin.testDateTimeOffset.model; + +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.OffsetDateTime; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +@Data +public class TestDateDTO { + + @JsonProperty(value ="someDate") + private OffsetDateTime someDate; + + @JsonProperty(value ="someTime") + private OffsetDateTime someTime; + + + @Builder + @Jacksonized + private TestDateDTO(OffsetDateTime someDate, OffsetDateTime someTime) { + this.someDate = someDate; + this.someTime = someTime; + + } + +} diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/api-test.yml b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/api-test.yml new file mode 100644 index 00000000..3d9e1813 --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/api-test.yml @@ -0,0 +1,30 @@ +openapi: 3.0.2 +info: + title: Testing example file + version: 1.0.0 +servers: +- url: http://localhost/v1 +paths: + /test: + get: + tags: + - test + operationId: testDateTime + responses: + '200': + description: An object with date and date-time formats + content: + application/json: + schema: + $ref: '#/components/schemas/testDate' +components: + schemas: + testDate: + type: object + properties: + someDate: + type: string + format: date + someTime: + type: string + format: date-time diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/assets/TestApi.java b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/assets/TestApi.java new file mode 100644 index 00000000..a5b31dee --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/assets/TestApi.java @@ -0,0 +1,45 @@ +package com.sngular.multifileplugin.testDateTimeZoned; + +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.testDateTimeZoned.model.TestDateDTO; + +public interface TestApi { + + /** + * GET /test + * @return An object with date and date-time formats; (status code 200) + */ + + @Operation( + operationId = "testDateTime", + tags = {"test"}, + responses = { + @ApiResponse(responseCode = "200", description = "An object with date and date-time formats", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDateDTO.class))) + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = "/test", + produces = {"application/json"} + ) + + default ResponseEntity testDateTime() { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + +} diff --git a/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/assets/model/TestDateDTO.java b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/assets/model/TestDateDTO.java new file mode 100644 index 00000000..24a25b9e --- /dev/null +++ b/multiapi-engine/src/test/resources/openapigenerator/testDateTimeZoned/assets/model/TestDateDTO.java @@ -0,0 +1,29 @@ +package com.sngular.multifileplugin.testDateTimeZoned.model; + +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.ZonedDateTime; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; + +@Data +public class TestDateDTO { + + @JsonProperty(value ="someDate") + private ZonedDateTime someDate; + + @JsonProperty(value ="someTime") + private ZonedDateTime someTime; + + + @Builder + @Jacksonized + private TestDateDTO(ZonedDateTime someDate, ZonedDateTime someTime) { + this.someDate = someDate; + this.someTime = someTime; + + } + +} diff --git a/scs-multiapi-gradle-plugin/build.gradle b/scs-multiapi-gradle-plugin/build.gradle index 35fffb20..ae50bda6 100644 --- a/scs-multiapi-gradle-plugin/build.gradle +++ b/scs-multiapi-gradle-plugin/build.gradle @@ -20,7 +20,7 @@ repositories { } group = 'com.sngular' -version = '4.5.2' +version = '4.6.0' def SCSMultiApiPluginGroupId = group def SCSMultiApiPluginVersion = version @@ -30,7 +30,7 @@ dependencies { shadow localGroovy() shadow gradleApi() - implementation 'com.sngular:multiapi-engine:4.5.2' + implementation 'com.sngular:multiapi-engine:4.6.0' testImplementation 'org.assertj:assertj-core:3.23.1' testImplementation 'com.puppycrawl.tools:checkstyle:10.3.1' } @@ -98,7 +98,7 @@ testing { integrationTest(JvmTestSuite) { dependencies { - implementation 'com.sngular:scs-multiapi-gradle-plugin:4.5.2' + implementation 'com.sngular:scs-multiapi-gradle-plugin:4.6.0' implementation 'org.assertj:assertj-core:3.23.1' } diff --git a/scs-multiapi-maven-plugin/pom.xml b/scs-multiapi-maven-plugin/pom.xml index d0e52d85..b1a8a1d4 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 - 4.5.2 + 4.6.0 maven-plugin AsyncApi - OpenApi Code Generator Maven Plugin @@ -144,9 +144,9 @@ Europe/Madrid - davidgayoso - David Gayoso Salvado - david.gayoso@sngular.com + 5uso-sng + Jesús Mosteiro García + jesus.mosteiro@sngular.com Sngular https://www.sngular.com @@ -155,9 +155,9 @@ Europe/Madrid - janDuinRod - Jan Duinkerken Rodríguez - jan.duinkerken@sngular.com + davidgayoso + David Gayoso Salvado + david.gayoso@sngular.com Sngular https://www.sngular.com @@ -166,9 +166,9 @@ Europe/Madrid - 5uso-sng - Jesús Mosteiro García - jesus.mosteiro@sngular.com + janDuinRod + Jan Duinkerken Rodríguez + jan.duinkerken@sngular.com Sngular https://www.sngular.com @@ -223,7 +223,7 @@ com.sngular multiapi-engine - 4.5.2 + 4.6.0 org.apache.maven @@ -392,6 +392,7 @@ + org.apache.maven.plugins maven-assembly-plugin 3.4.2 From 5f51e6e4c46dd5dbc728215c2aae3c1eacc48ed3 Mon Sep 17 00:00:00 2001 From: Suso <126153639+5uso-sng@users.noreply.github.com> Date: Wed, 12 Apr 2023 13:13:36 +0200 Subject: [PATCH 2/3] 176 missing dates types in openapi (Rerun deployment) (#201) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #177 Fix embedded object generation * Slight code cleanup * Add missing license notice * Added date types to FieldObjectType mappings * Type constants consistency We somehow had these duplicated in three different places, with inconsistent capitalization * Added date and date-time test * #176 Added support for date and date-time formats * #176 Added Zoned and Offset time options Configured within the SpecFile * Fixed checkstyle violations * Updated version #185 Should be a patch, so changing the version number to 4.6.0 should work regardless of merge order * Make empty restrictionProperties the default * Post-merge checkstyle * Updated readme with useTimeType * Change deploy parameters * Deployment command fix * Update version --------- Co-authored-by: Jose Enrique García Maciñeiras --- .github/workflows/maven-central-push.yml | 2 +- multiapi-engine/pom.xml | 2 +- scs-multiapi-gradle-plugin/build.gradle | 6 +++--- scs-multiapi-maven-plugin/pom.xml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/maven-central-push.yml b/.github/workflows/maven-central-push.yml index ba23c4a0..e7264976 100644 --- a/.github/workflows/maven-central-push.yml +++ b/.github/workflows/maven-central-push.yml @@ -71,7 +71,7 @@ jobs: # Uses production profile to sign with gpg plugin run: | cd scs-multiapi-maven-plugin - mvn deploy -DskipLocalStaging=true -P production --file pom-xml + mvn deploy -DskipLocalStaging=true -P production --file pom.xml env: MAVEN_USERNAME: ${{ secrets.JIRAID }} MAVEN_CENTRAL_TOKEN: ${{ secrets.JIRAPASS }} diff --git a/multiapi-engine/pom.xml b/multiapi-engine/pom.xml index 78f0af1c..93bf5ef8 100644 --- a/multiapi-engine/pom.xml +++ b/multiapi-engine/pom.xml @@ -4,7 +4,7 @@ com.sngular multiapi-engine - 4.6.0 + 4.6.1 jar diff --git a/scs-multiapi-gradle-plugin/build.gradle b/scs-multiapi-gradle-plugin/build.gradle index ae50bda6..f5175620 100644 --- a/scs-multiapi-gradle-plugin/build.gradle +++ b/scs-multiapi-gradle-plugin/build.gradle @@ -20,7 +20,7 @@ repositories { } group = 'com.sngular' -version = '4.6.0' +version = '4.6.1' def SCSMultiApiPluginGroupId = group def SCSMultiApiPluginVersion = version @@ -30,7 +30,7 @@ dependencies { shadow localGroovy() shadow gradleApi() - implementation 'com.sngular:multiapi-engine:4.6.0' + implementation 'com.sngular:multiapi-engine:4.6.1' testImplementation 'org.assertj:assertj-core:3.23.1' testImplementation 'com.puppycrawl.tools:checkstyle:10.3.1' } @@ -98,7 +98,7 @@ testing { integrationTest(JvmTestSuite) { dependencies { - implementation 'com.sngular:scs-multiapi-gradle-plugin:4.6.0' + implementation 'com.sngular:scs-multiapi-gradle-plugin:4.6.1' implementation 'org.assertj:assertj-core:3.23.1' } diff --git a/scs-multiapi-maven-plugin/pom.xml b/scs-multiapi-maven-plugin/pom.xml index b1a8a1d4..deb2c7fc 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 - 4.6.0 + 4.6.1 maven-plugin AsyncApi - OpenApi Code Generator Maven Plugin @@ -223,7 +223,7 @@ com.sngular multiapi-engine - 4.6.0 + 4.6.1 org.apache.maven From 85affd9363e69815e0585d094899820efe9ba126 Mon Sep 17 00:00:00 2001 From: OlgaCalderon <127837946+OlgaCalderon@users.noreply.github.com> Date: Thu, 20 Apr 2023 10:58:31 +0200 Subject: [PATCH 3/3] 204 Fixes typo in action update-wiki.yml (#206) --- .github/workflows/update-wiki.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-wiki.yml b/.github/workflows/update-wiki.yml index 2665d943..90125fb8 100644 --- a/.github/workflows/update-wiki.yml +++ b/.github/workflows/update-wiki.yml @@ -55,4 +55,4 @@ jobs: git add . git commit -m "scs-multiapi-plugin documentation | GitHub Actions $GITHUB_WORKFLOW $GITHUB_RUN_NUMBER" git remote add origin-wiki "https://${{secrets.GITBOT_TOKEN}}@github.com/sngular/scs-multiapi-plugin.wiki.git" - git push origin-wiki master + git push origin-wiki main