diff --git a/.github/workflows/gradle-portal-push.yml b/.github/workflows/gradle-portal-push.yml index e32555c8..1e57b604 100644 --- a/.github/workflows/gradle-portal-push.yml +++ b/.github/workflows/gradle-portal-push.yml @@ -50,10 +50,10 @@ jobs: with: ref: ${{ github.head_ref }} - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v2 with: - java-version: "17" + java-version: "21" distribution: "adopt" server-id: ossrh server-username: MAVEN_USERNAME diff --git a/multiapi-engine/pom.xml b/multiapi-engine/pom.xml index 86cffc01..4a6918a1 100644 --- a/multiapi-engine/pom.xml +++ b/multiapi-engine/pom.xml @@ -4,7 +4,7 @@ com.sngular multiapi-engine - 6.5.1 + 6.5.3 jar diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/model/SchemaFieldObject.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/model/SchemaFieldObject.java index 117a998f..638a811b 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/model/SchemaFieldObject.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/model/SchemaFieldObject.java @@ -32,4 +32,6 @@ public class SchemaFieldObject { private String description; private String example; + + private boolean deprecated; } diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ApiTool.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ApiTool.java index 7de70e5c..d6872a2e 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ApiTool.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ApiTool.java @@ -484,6 +484,10 @@ public static String getDescription(final JsonNode schema) { return getNodeAsString(schema, "description"); } + public static boolean isDeprecated(final JsonNode schema) { + return getNodeAsBoolean(schema, "deprecated"); + } + public static String getExample(final JsonNode schema) { // OpenAPI 3.0 uses a single `example`; OpenAPI 3.1 / JSON Schema 2020-12 use an // `examples` array. Prefer `example`, otherwise take the first `examples` entry. diff --git a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java index 5172950e..6a5c49f5 100644 --- a/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java +++ b/multiapi-engine/src/main/java/com/sngular/api/generator/plugin/common/tools/ModelBuilder.java @@ -346,7 +346,8 @@ private static List processObjectProperty( private static void applyMetadata(final List fields, final String fieldName, final JsonNode fieldBody) { final String description = ApiTool.getDescription(fieldBody); final String example = ApiTool.getExample(fieldBody); - if (Objects.isNull(description) && Objects.isNull(example)) { + final boolean deprecated = ApiTool.isDeprecated(fieldBody); + if (Objects.isNull(description) && Objects.isNull(example) && !deprecated) { return; } for (final var field : fields) { @@ -357,6 +358,9 @@ private static void applyMetadata(final List fields, final St if (Objects.nonNull(example)) { field.setExample(example); } + if (deprecated) { + field.setDeprecated(true); + } } } } @@ -872,6 +876,11 @@ private static SchemaFieldObject processEnumField( throw new BadDefinedEnumException(name); } field.setEnumValues(enumValuesMap); + // Enum fields bypass processObjectProperty's applyMetadata, so carry the schema's + // description/example/deprecated here too for consistent @Schema annotations. + field.setDescription(ApiTool.getDescription(value)); + field.setExample(ApiTool.getExample(value)); + field.setDeprecated(ApiTool.isDeprecated(value)); return field; } diff --git a/multiapi-engine/src/main/resources/templates/model/templateSchema.ftlh b/multiapi-engine/src/main/resources/templates/model/templateSchema.ftlh index daf298d2..6d9e5bc1 100644 --- a/multiapi-engine/src/main/resources/templates/model/templateSchema.ftlh +++ b/multiapi-engine/src/main/resources/templates/model/templateSchema.ftlh @@ -340,7 +340,7 @@ public class ${schema.className} { } <#list schema.fieldObjectList as field> - @Schema(name = "${field.baseName?uncap_first}", required = <#if field.required?has_content && field.required == true>true<#else>false<#if field.description?has_content>, description = "${field.description?j_string}"<#if field.example?has_content>, example = "${field.example?j_string}") + @Schema(name = "${field.baseName?uncap_first}", required = <#if field.required?has_content && field.required == true>true<#else>false<#if field.description?has_content>, description = "${field.description?j_string}"<#if field.example?has_content>, example = "${field.example?j_string}"<#if field.deprecated>, deprecated = true) <#if field.dataType.baseType == "array"> public ${field.dataType} get${field.baseName?cap_first}() { return ${calculateSafeName (field.baseName, ";")} diff --git a/multiapi-engine/src/test/resources/openapigenerator/testOpenApi31Completeness/api-test.yml b/multiapi-engine/src/test/resources/openapigenerator/testOpenApi31Completeness/api-test.yml index f96902cc..53b78032 100644 --- a/multiapi-engine/src/test/resources/openapigenerator/testOpenApi31Completeness/api-test.yml +++ b/multiapi-engine/src/test/resources/openapigenerator/testOpenApi31Completeness/api-test.yml @@ -42,6 +42,9 @@ components: description: The unique gadget identifier examples: - "gadget-001" + legacyId: + type: string + deprecated: true serial: type: ["string", "null"] example: "SN-12345" @@ -58,6 +61,12 @@ components: patternProperties: "^x-": type: string + status: + type: string + description: Lifecycle status of the gadget + enum: + - ACTIVE + - RETIRED nothing: type: "null" owner: diff --git a/multiapi-engine/src/test/resources/openapigenerator/testOpenApi31Completeness/assets/GadgetDTO.java b/multiapi-engine/src/test/resources/openapigenerator/testOpenApi31Completeness/assets/GadgetDTO.java index 2356a400..06d53cb7 100644 --- a/multiapi-engine/src/test/resources/openapigenerator/testOpenApi31Completeness/assets/GadgetDTO.java +++ b/multiapi-engine/src/test/resources/openapigenerator/testOpenApi31Completeness/assets/GadgetDTO.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -16,6 +17,30 @@ @JsonDeserialize(builder = GadgetDTO.GadgetDTOBuilder.class) public class GadgetDTO { + @JsonProperty(value ="status") + private Status status; + public enum Status { + ACTIVE("ACTIVE"), + RETIRED("RETIRED"); + + private String value; + + Status(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + @JsonProperty(value ="legacyId") + private String legacyId; @JsonProperty(value ="payload") private MultipartFile payload; @JsonProperty(value ="nothing") @@ -32,6 +57,8 @@ public class GadgetDTO { private String serial; private GadgetDTO(GadgetDTOBuilder builder) { + this.status = builder.status; + this.legacyId = builder.legacyId; this.payload = builder.payload; this.nothing = builder.nothing; this.id = builder.id; @@ -49,6 +76,8 @@ public static GadgetDTO.GadgetDTOBuilder builder() { @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "") public static class GadgetDTOBuilder { + private Status status; + private String legacyId; private MultipartFile payload; private Object nothing; private String id; @@ -57,6 +86,16 @@ public static class GadgetDTOBuilder { private PersonDTO owner; private String serial; + public GadgetDTO.GadgetDTOBuilder status(Status status) { + this.status = status; + return this; + } + + public GadgetDTO.GadgetDTOBuilder legacyId(String legacyId) { + this.legacyId = legacyId; + return this; + } + public GadgetDTO.GadgetDTOBuilder payload(MultipartFile payload) { this.payload = payload; return this; @@ -112,6 +151,22 @@ public GadgetDTO build() { } } + @Schema(name = "status", required = false, description = "Lifecycle status of the gadget") + public Status getStatus() { + return status; + } + public void setStatus(Status status) { + this.status = status; + } + + @Schema(name = "legacyId", required = false, deprecated = true) + public String getLegacyId() { + return legacyId; + } + public void setLegacyId(String legacyId) { + this.legacyId = legacyId; + } + @Schema(name = "payload", required = false) public MultipartFile getPayload() { return payload; @@ -177,18 +232,20 @@ public boolean equals(Object o) { return false; } GadgetDTO gadgetDTO = (GadgetDTO) o; - return Objects.equals(this.payload, gadgetDTO.payload) && Objects.equals(this.nothing, gadgetDTO.nothing) && Objects.equals(this.id, gadgetDTO.id) && Objects.equals(this.metadata, gadgetDTO.metadata) && Objects.equals(this.coords, gadgetDTO.coords) && Objects.equals(this.owner, gadgetDTO.owner) && Objects.equals(this.serial, gadgetDTO.serial); + return Objects.equals(this.status, gadgetDTO.status) && Objects.equals(this.legacyId, gadgetDTO.legacyId) && Objects.equals(this.payload, gadgetDTO.payload) && Objects.equals(this.nothing, gadgetDTO.nothing) && Objects.equals(this.id, gadgetDTO.id) && Objects.equals(this.metadata, gadgetDTO.metadata) && Objects.equals(this.coords, gadgetDTO.coords) && Objects.equals(this.owner, gadgetDTO.owner) && Objects.equals(this.serial, gadgetDTO.serial); } @Override public int hashCode() { - return Objects.hash(payload, nothing, id, metadata, coords, owner, serial); + return Objects.hash(status, legacyId, payload, nothing, id, metadata, coords, owner, serial); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("GadgetDTO{"); + sb.append(" status:").append(status).append(","); + sb.append(" legacyId:").append(legacyId).append(","); sb.append(" payload:").append(payload).append(","); sb.append(" nothing:").append(nothing).append(","); sb.append(" id:").append(id).append(","); diff --git a/scs-multiapi-gradle-plugin/build.gradle b/scs-multiapi-gradle-plugin/build.gradle index d750506a..82437b6d 100644 --- a/scs-multiapi-gradle-plugin/build.gradle +++ b/scs-multiapi-gradle-plugin/build.gradle @@ -21,7 +21,7 @@ repositories { } group = 'com.sngular' -version = '6.5.1' +version = '6.5.3' def SCSMultiApiPluginGroupId = group def SCSMultiApiPluginVersion = version @@ -31,7 +31,7 @@ dependencies { shadow localGroovy() shadow gradleApi() - implementation 'com.sngular:multiapi-engine:6.5.1' + implementation 'com.sngular:multiapi-engine:6.5.3' testImplementation 'org.assertj:assertj-core:3.24.2' testImplementation 'com.puppycrawl.tools:checkstyle:10.12.3' testImplementation 'org.junit.platform:junit-platform-launcher:1.9.2' @@ -100,7 +100,7 @@ testing { integrationTest(JvmTestSuite) { dependencies { - implementation 'com.sngular:scs-multiapi-gradle-plugin:6.5.1' + implementation 'com.sngular:scs-multiapi-gradle-plugin:6.5.3' implementation 'org.assertj:assertj-core:3.24.2' } diff --git a/scs-multiapi-maven-plugin/pom.xml b/scs-multiapi-maven-plugin/pom.xml index eaa78b50..ce1f5329 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 - 6.5.1 + 6.5.3 maven-plugin AsyncApi - OpenApi Code Generator Maven Plugin @@ -271,7 +271,7 @@ com.sngular multiapi-engine - 6.5.1 + 6.5.3 org.apache.maven