From 2dbf9223f46b307230f1c4a7bf175243fffd1754 Mon Sep 17 00:00:00 2001 From: gabriel-farache Date: Wed, 28 Jun 2023 14:22:12 +0200 Subject: [PATCH 1/2] Return Checkers in WorkFlowDefinitions --- .../parodos/flows/PrebuiltWorkFlowTest.java | 14 ++- .../parodos/flows/SimpleWorkFlowTest.java | 25 ++-- .../FailedWithAlertMessageWorkFlowTest.java | 15 +-- .../PendingWithAlertMessageWorkFlowTest.java | 15 +-- ...entialFailedWithExceptionWorkFlowTest.java | 15 ++- .../SequentialFailedWorkFlowTest.java | 15 ++- .../parodos/workflow/enums/WorkType.java | 2 +- workflow-service-sdk/api/openapi.yaml | 8 ++ .../docs/WorkDefinitionResponseDTO.md | 3 +- .../docs/WorkFlowDefinitionResponseDTO.md | 3 +- workflow-service-sdk/docs/WorkRequestDTO.md | 1 + .../docs/WorkStatusResponseDTO.md | 1 + .../sdk/model/WorkDefinitionResponseDTO.java | 15 ++- .../model/WorkFlowDefinitionResponseDTO.java | 50 ++++++-- .../parodos/sdk/model/WorkRequestDTO.java | 4 +- .../sdk/model/WorkStatusResponseDTO.java | 4 +- .../generated/openapi/openapi.json | 10 +- .../dto/WorkDefinitionResponseDTO.java | 28 ++++- .../dto/WorkFlowDefinitionResponseDTO.java | 20 ++- .../WorkFlowDefinitionServiceImpl.java | 119 ++++++++++++------ .../workflow/WorkFlowDelegateTest.java | 5 +- .../WorkFlowDefinitionControllerTest.java | 3 +- .../WorkFlowDefinitionServiceImplTest.java | 9 +- .../service/WorkFlowServiceImplTest.java | 9 +- 24 files changed, 262 insertions(+), 131 deletions(-) diff --git a/integration-tests/src/test/java/com/redhat/parodos/flows/PrebuiltWorkFlowTest.java b/integration-tests/src/test/java/com/redhat/parodos/flows/PrebuiltWorkFlowTest.java index 9c56ce32c..bae6cc25c 100644 --- a/integration-tests/src/test/java/com/redhat/parodos/flows/PrebuiltWorkFlowTest.java +++ b/integration-tests/src/test/java/com/redhat/parodos/flows/PrebuiltWorkFlowTest.java @@ -2,6 +2,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.function.Consumer; import com.redhat.parodos.flows.common.WorkFlowTestBuilder; @@ -79,12 +80,13 @@ private Consumer getWorkFlowDefinitionResponseCon assertNotNull(workFlowDefinition.getWorks()); assertEquals(1, workFlowDefinition.getWorks().size()); - assertEquals("notificationTask", workFlowDefinition.getWorks().get(0).getName()); - assertEquals(WorkDefinitionResponseDTO.WorkTypeEnum.TASK, - workFlowDefinition.getWorks().get(0).getWorkType()); - assertTrue(CollectionUtils.isEmpty(workFlowDefinition.getWorks().get(0).getWorks())); - assertNull(workFlowDefinition.getWorks().get(0).getProcessingType()); - assertNotNull(workFlowDefinition.getWorks().get(0).getParameters()); + Optional firstWork = workFlowDefinition.getWorks().stream().findFirst(); + assertTrue(firstWork.isPresent()); + assertEquals("notificationTask", firstWork.get().getName()); + assertEquals(WorkDefinitionResponseDTO.WorkTypeEnum.TASK, firstWork.get().getWorkType()); + assertTrue(CollectionUtils.isEmpty(firstWork.get().getWorks())); + assertNull(firstWork.get().getProcessingType()); + assertNotNull(firstWork.get().getParameters()); }; } diff --git a/integration-tests/src/test/java/com/redhat/parodos/flows/SimpleWorkFlowTest.java b/integration-tests/src/test/java/com/redhat/parodos/flows/SimpleWorkFlowTest.java index ab9aa0536..15f4b2b5a 100644 --- a/integration-tests/src/test/java/com/redhat/parodos/flows/SimpleWorkFlowTest.java +++ b/integration-tests/src/test/java/com/redhat/parodos/flows/SimpleWorkFlowTest.java @@ -90,19 +90,18 @@ private static Consumer getWorkFlowDefinitionResp assertNotNull(workFlowDefinition.getWorks()); assertEquals(2, workFlowDefinition.getWorks().size()); - assertEquals("restCallTask", workFlowDefinition.getWorks().get(0).getName()); - assertEquals(WorkDefinitionResponseDTO.WorkTypeEnum.TASK, - workFlowDefinition.getWorks().get(0).getWorkType()); - assertTrue(CollectionUtils.isEmpty(workFlowDefinition.getWorks().get(0).getWorks())); - assertNull(workFlowDefinition.getWorks().get(0).getProcessingType()); - assertNotNull(workFlowDefinition.getWorks().get(0).getParameters()); - - assertEquals("loggingTask", workFlowDefinition.getWorks().get(1).getName()); - assertEquals(WorkDefinitionResponseDTO.WorkTypeEnum.TASK, - workFlowDefinition.getWorks().get(1).getWorkType()); - assertTrue(CollectionUtils.isEmpty(workFlowDefinition.getWorks().get(1).getWorks())); - assertNull(workFlowDefinition.getWorks().get(1).getProcessingType()); - assertNotNull(workFlowDefinition.getWorks().get(1).getParameters()); + List works = workFlowDefinition.getWorks().stream().toList(); + assertEquals("restCallTask", works.get(0).getName()); + assertEquals(WorkDefinitionResponseDTO.WorkTypeEnum.TASK, works.get(0).getWorkType()); + assertTrue(CollectionUtils.isEmpty(works.get(0).getWorks())); + assertNull(works.get(0).getProcessingType()); + assertNotNull(works.get(0).getParameters()); + + assertEquals("loggingTask", works.get(1).getName()); + assertEquals(WorkDefinitionResponseDTO.WorkTypeEnum.TASK, works.get(1).getWorkType()); + assertTrue(CollectionUtils.isEmpty(works.get(1).getWorks())); + assertNull(works.get(1).getProcessingType()); + assertNotNull(works.get(1).getParameters()); }; } diff --git a/integration-tests/src/test/java/com/redhat/parodos/flows/negative/FailedWithAlertMessageWorkFlowTest.java b/integration-tests/src/test/java/com/redhat/parodos/flows/negative/FailedWithAlertMessageWorkFlowTest.java index 936842d8c..4dac01bfb 100644 --- a/integration-tests/src/test/java/com/redhat/parodos/flows/negative/FailedWithAlertMessageWorkFlowTest.java +++ b/integration-tests/src/test/java/com/redhat/parodos/flows/negative/FailedWithAlertMessageWorkFlowTest.java @@ -1,5 +1,6 @@ package com.redhat.parodos.flows.negative; +import java.util.List; import java.util.function.Consumer; import com.redhat.parodos.flows.common.WorkFlowTestBuilder; @@ -86,13 +87,13 @@ private static Consumer getWorkFlowDefinitionResp assertThat(workFlowDefinition.getWorks()).isNotNull(); assertThat(workFlowDefinition.getWorks()).hasSize(2); - assertThat(workFlowDefinition.getWorks().get(1).getName()).isEqualTo("doNothingAgainWorkFlowTask"); - assertThat(workFlowDefinition.getWorks().get(1).getWorkType()) - .isEqualTo(WorkDefinitionResponseDTO.WorkTypeEnum.TASK); - assertThat(workFlowDefinition.getWorks().get(1).getWorks()).isNullOrEmpty(); - assertThat(workFlowDefinition.getWorks().get(1).getProcessingType()).isNull(); - assertThat(workFlowDefinition.getWorks().get(1).getParameters()).isNotNull(); - assertThat(workFlowDefinition.getWorks().get(0).getName()).isEqualTo("failedWithAlertMessageWorkFlowTask"); + List works = workFlowDefinition.getWorks().stream().toList(); + assertThat(works.get(1).getName()).isEqualTo("doNothingAgainWorkFlowTask"); + assertThat(works.get(1).getWorkType()).isEqualTo(WorkDefinitionResponseDTO.WorkTypeEnum.TASK); + assertThat(works.get(1).getWorks()).isNullOrEmpty(); + assertThat(works.get(1).getProcessingType()).isNull(); + assertThat(works.get(1).getParameters()).isNotNull(); + assertThat(works.get(0).getName()).isEqualTo("failedWithAlertMessageWorkFlowTask"); }; } diff --git a/integration-tests/src/test/java/com/redhat/parodos/flows/negative/PendingWithAlertMessageWorkFlowTest.java b/integration-tests/src/test/java/com/redhat/parodos/flows/negative/PendingWithAlertMessageWorkFlowTest.java index 30b79b05f..862d04d32 100644 --- a/integration-tests/src/test/java/com/redhat/parodos/flows/negative/PendingWithAlertMessageWorkFlowTest.java +++ b/integration-tests/src/test/java/com/redhat/parodos/flows/negative/PendingWithAlertMessageWorkFlowTest.java @@ -1,5 +1,6 @@ package com.redhat.parodos.flows.negative; +import java.util.List; import java.util.function.Consumer; import com.redhat.parodos.flows.common.WorkFlowTestBuilder; @@ -86,13 +87,13 @@ private static Consumer getWorkFlowDefinitionResp assertThat(workFlowDefinition.getWorks()).isNotNull(); assertThat(workFlowDefinition.getWorks()).hasSize(2); - assertThat(workFlowDefinition.getWorks().get(1).getName()).isEqualTo("doNothingWorkFlowTask"); - assertThat(workFlowDefinition.getWorks().get(1).getWorkType()) - .isEqualTo(WorkDefinitionResponseDTO.WorkTypeEnum.TASK); - assertThat(workFlowDefinition.getWorks().get(1).getWorks()).isNullOrEmpty(); - assertThat(workFlowDefinition.getWorks().get(1).getProcessingType()).isNull(); - assertThat(workFlowDefinition.getWorks().get(1).getParameters()).isNotNull(); - assertThat(workFlowDefinition.getWorks().get(0).getName()).isEqualTo("pendingWithAlertMessageWorkFlowTask"); + List works = workFlowDefinition.getWorks().stream().toList(); + assertThat(works.get(1).getName()).isEqualTo("doNothingWorkFlowTask"); + assertThat(works.get(1).getWorkType()).isEqualTo(WorkDefinitionResponseDTO.WorkTypeEnum.TASK); + assertThat(works.get(1).getWorks()).isNullOrEmpty(); + assertThat(works.get(1).getProcessingType()).isNull(); + assertThat(works.get(1).getParameters()).isNotNull(); + assertThat(works.get(0).getName()).isEqualTo("pendingWithAlertMessageWorkFlowTask"); }; } diff --git a/integration-tests/src/test/java/com/redhat/parodos/flows/negative/SequentialFailedWithExceptionWorkFlowTest.java b/integration-tests/src/test/java/com/redhat/parodos/flows/negative/SequentialFailedWithExceptionWorkFlowTest.java index 6a9aec9ad..07be3d7fd 100644 --- a/integration-tests/src/test/java/com/redhat/parodos/flows/negative/SequentialFailedWithExceptionWorkFlowTest.java +++ b/integration-tests/src/test/java/com/redhat/parodos/flows/negative/SequentialFailedWithExceptionWorkFlowTest.java @@ -1,5 +1,6 @@ package com.redhat.parodos.flows.negative; +import java.util.Optional; import java.util.function.Consumer; import com.redhat.parodos.flows.common.WorkFlowTestBuilder; @@ -21,6 +22,7 @@ import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; @Slf4j public class SequentialFailedWithExceptionWorkFlowTest { @@ -77,12 +79,13 @@ private static Consumer getWorkFlowDefinitionResp assertThat(workFlowDefinition.getWorks()).isNotNull(); assertThat(workFlowDefinition.getWorks()).hasSize(1); - assertThat(workFlowDefinition.getWorks().get(0).getName()).isEqualTo("failedWithExceptionWorkFlowTask"); - assertThat(workFlowDefinition.getWorks().get(0).getWorkType()) - .isEqualTo(WorkDefinitionResponseDTO.WorkTypeEnum.TASK); - assertThat(workFlowDefinition.getWorks().get(0).getWorks()).isNullOrEmpty(); - assertThat(workFlowDefinition.getWorks().get(0).getProcessingType()).isNull(); - assertThat(workFlowDefinition.getWorks().get(0).getParameters()).isNotNull(); + Optional firstWork = workFlowDefinition.getWorks().stream().findFirst(); + assertTrue(firstWork.isPresent()); + assertThat(firstWork.get().getName()).isEqualTo("failedWithExceptionWorkFlowTask"); + assertThat(firstWork.get().getWorkType()).isEqualTo(WorkDefinitionResponseDTO.WorkTypeEnum.TASK); + assertThat(firstWork.get().getWorks()).isNullOrEmpty(); + assertThat(firstWork.get().getProcessingType()).isNull(); + assertThat(firstWork.get().getParameters()).isNotNull(); }; } diff --git a/integration-tests/src/test/java/com/redhat/parodos/flows/negative/SequentialFailedWorkFlowTest.java b/integration-tests/src/test/java/com/redhat/parodos/flows/negative/SequentialFailedWorkFlowTest.java index 71cd71b82..234d0d0dc 100644 --- a/integration-tests/src/test/java/com/redhat/parodos/flows/negative/SequentialFailedWorkFlowTest.java +++ b/integration-tests/src/test/java/com/redhat/parodos/flows/negative/SequentialFailedWorkFlowTest.java @@ -1,5 +1,6 @@ package com.redhat.parodos.flows.negative; +import java.util.Optional; import java.util.function.Consumer; import com.redhat.parodos.flows.common.WorkFlowTestBuilder; @@ -21,6 +22,7 @@ import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; @Slf4j public class SequentialFailedWorkFlowTest { @@ -74,12 +76,13 @@ private static Consumer getWorkFlowDefinitionResp assertThat(workFlowDefinition.getWorks()).isNotNull(); assertThat(workFlowDefinition.getWorks()).hasSize(1); - assertThat(workFlowDefinition.getWorks().get(0).getName()).isEqualTo("failedWorkFlowTask"); - assertThat(workFlowDefinition.getWorks().get(0).getWorkType()) - .isEqualTo(WorkDefinitionResponseDTO.WorkTypeEnum.TASK); - assertThat(workFlowDefinition.getWorks().get(0).getWorks()).isNullOrEmpty(); - assertThat(workFlowDefinition.getWorks().get(0).getProcessingType()).isNull(); - assertThat(workFlowDefinition.getWorks().get(0).getParameters()).isNotNull(); + Optional firstWork = workFlowDefinition.getWorks().stream().findFirst(); + assertTrue(firstWork.isPresent()); + assertThat(firstWork.get().getName()).isEqualTo("failedWorkFlowTask"); + assertThat(firstWork.get().getWorkType()).isEqualTo(WorkDefinitionResponseDTO.WorkTypeEnum.TASK); + assertThat(firstWork.get().getWorks()).isNullOrEmpty(); + assertThat(firstWork.get().getProcessingType()).isNull(); + assertThat(firstWork.get().getParameters()).isNotNull(); }; } diff --git a/parodos-model-api/src/main/java/com/redhat/parodos/workflow/enums/WorkType.java b/parodos-model-api/src/main/java/com/redhat/parodos/workflow/enums/WorkType.java index 7d3f2f6bc..932b48d97 100644 --- a/parodos-model-api/src/main/java/com/redhat/parodos/workflow/enums/WorkType.java +++ b/parodos-model-api/src/main/java/com/redhat/parodos/workflow/enums/WorkType.java @@ -24,6 +24,6 @@ */ public enum WorkType { - TASK, WORKFLOW + TASK, WORKFLOW, CHECKER } diff --git a/workflow-service-sdk/api/openapi.yaml b/workflow-service-sdk/api/openapi.yaml index ae3a0e56c..75b725138 100644 --- a/workflow-service-sdk/api/openapi.yaml +++ b/workflow-service-sdk/api/openapi.yaml @@ -1289,11 +1289,13 @@ components: enum: - TASK - WORKFLOW + - CHECKER type: string works: items: $ref: '#/components/schemas/WorkDefinitionResponseDTO' type: array + uniqueItems: true type: object WorkFlowCheckerTaskRequestDTO: example: @@ -1415,6 +1417,7 @@ components: type: object WorkFlowDefinitionResponseDTO: example: + cronExpression: cronExpression processingType: SEQUENTIAL works: - outputs: @@ -1463,6 +1466,8 @@ components: createDate: format: date-time type: string + cronExpression: + type: string fallbackWorkflow: type: string id: @@ -1498,6 +1503,7 @@ components: items: $ref: '#/components/schemas/WorkDefinitionResponseDTO' type: array + uniqueItems: true type: object WorkFlowExecutionResponseDTO: example: @@ -1880,6 +1886,7 @@ components: enum: - TASK - WORKFLOW + - CHECKER type: string workName: type: string @@ -1917,6 +1924,7 @@ components: enum: - TASK - WORKFLOW + - CHECKER type: string works: items: diff --git a/workflow-service-sdk/docs/WorkDefinitionResponseDTO.md b/workflow-service-sdk/docs/WorkDefinitionResponseDTO.md index 9a2ab7c7b..3faa8d2df 100644 --- a/workflow-service-sdk/docs/WorkDefinitionResponseDTO.md +++ b/workflow-service-sdk/docs/WorkDefinitionResponseDTO.md @@ -14,7 +14,7 @@ |**parameters** | **Map<String, Map<String, Object>>** | | [optional] | |**processingType** | [**ProcessingTypeEnum**](#ProcessingTypeEnum) | | [optional] | |**workType** | [**WorkTypeEnum**](#WorkTypeEnum) | | [optional] | -|**works** | [**List<WorkDefinitionResponseDTO>**](WorkDefinitionResponseDTO.md) | | [optional] | +|**works** | [**Set<WorkDefinitionResponseDTO>**](WorkDefinitionResponseDTO.md) | | [optional] | @@ -45,6 +45,7 @@ |---- | -----| | TASK | "TASK" | | WORKFLOW | "WORKFLOW" | +| CHECKER | "CHECKER" | diff --git a/workflow-service-sdk/docs/WorkFlowDefinitionResponseDTO.md b/workflow-service-sdk/docs/WorkFlowDefinitionResponseDTO.md index 178cf4437..dd54b0b4a 100644 --- a/workflow-service-sdk/docs/WorkFlowDefinitionResponseDTO.md +++ b/workflow-service-sdk/docs/WorkFlowDefinitionResponseDTO.md @@ -9,6 +9,7 @@ |------------ | ------------- | ------------- | -------------| |**author** | **String** | | [optional] | |**createDate** | **Date** | | [optional] | +|**cronExpression** | **String** | | [optional] | |**fallbackWorkflow** | **String** | | [optional] | |**id** | **UUID** | | [optional] | |**modifyDate** | **Date** | | [optional] | @@ -17,7 +18,7 @@ |**processingType** | [**ProcessingTypeEnum**](#ProcessingTypeEnum) | | [optional] | |**properties** | [**WorkFlowPropertiesDefinitionDTO**](WorkFlowPropertiesDefinitionDTO.md) | | [optional] | |**type** | [**TypeEnum**](#TypeEnum) | | [optional] | -|**works** | [**List<WorkDefinitionResponseDTO>**](WorkDefinitionResponseDTO.md) | | [optional] | +|**works** | [**Set<WorkDefinitionResponseDTO>**](WorkDefinitionResponseDTO.md) | | [optional] | diff --git a/workflow-service-sdk/docs/WorkRequestDTO.md b/workflow-service-sdk/docs/WorkRequestDTO.md index e39c43723..9d59374f5 100644 --- a/workflow-service-sdk/docs/WorkRequestDTO.md +++ b/workflow-service-sdk/docs/WorkRequestDTO.md @@ -20,6 +20,7 @@ |---- | -----| | TASK | "TASK" | | WORKFLOW | "WORKFLOW" | +| CHECKER | "CHECKER" | diff --git a/workflow-service-sdk/docs/WorkStatusResponseDTO.md b/workflow-service-sdk/docs/WorkStatusResponseDTO.md index 97a45a254..6b3acc4d0 100644 --- a/workflow-service-sdk/docs/WorkStatusResponseDTO.md +++ b/workflow-service-sdk/docs/WorkStatusResponseDTO.md @@ -34,6 +34,7 @@ |---- | -----| | TASK | "TASK" | | WORKFLOW | "WORKFLOW" | +| CHECKER | "CHECKER" | diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkDefinitionResponseDTO.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkDefinitionResponseDTO.java index 17a43b0a8..e33a05d7d 100644 --- a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkDefinitionResponseDTO.java +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkDefinitionResponseDTO.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -188,7 +189,9 @@ public enum WorkTypeEnum { TASK("TASK"), - WORKFLOW("WORKFLOW"); + WORKFLOW("WORKFLOW"), + + CHECKER("CHECKER"); private String value; @@ -239,7 +242,7 @@ public WorkTypeEnum read(final JsonReader jsonReader) throws IOException { public static final String SERIALIZED_NAME_WORKS = "works"; @SerializedName(SERIALIZED_NAME_WORKS) - private List works; + private Set works; public WorkDefinitionResponseDTO() { } @@ -393,7 +396,7 @@ public void setWorkType(WorkTypeEnum workType) { this.workType = workType; } - public WorkDefinitionResponseDTO works(List works) { + public WorkDefinitionResponseDTO works(Set works) { this.works = works; return this; @@ -401,7 +404,7 @@ public WorkDefinitionResponseDTO works(List works) { public WorkDefinitionResponseDTO addWorksItem(WorkDefinitionResponseDTO worksItem) { if (this.works == null) { - this.works = new ArrayList<>(); + this.works = new LinkedHashSet<>(); } this.works.add(worksItem); return this; @@ -412,11 +415,11 @@ public WorkDefinitionResponseDTO addWorksItem(WorkDefinitionResponseDTO worksIte * @return works **/ @javax.annotation.Nullable - public List getWorks() { + public Set getWorks() { return works; } - public void setWorks(List works) { + public void setWorks(Set works) { this.works = works; } diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowDefinitionResponseDTO.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowDefinitionResponseDTO.java index 82e462150..ff2947213 100644 --- a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowDefinitionResponseDTO.java +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowDefinitionResponseDTO.java @@ -13,11 +13,10 @@ package com.redhat.parodos.sdk.model; import java.io.IOException; -import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.List; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; @@ -58,6 +57,11 @@ public class WorkFlowDefinitionResponseDTO { @SerializedName(SERIALIZED_NAME_FALLBACK_WORKFLOW) private String fallbackWorkflow; + public static final String SERIALIZED_NAME_CRON_EXPRESSION = "cronExpression"; + + @SerializedName(SERIALIZED_NAME_CRON_EXPRESSION) + private String cronExpression; + public static final String SERIALIZED_NAME_ID = "id"; @SerializedName(SERIALIZED_NAME_ID) @@ -204,7 +208,7 @@ public TypeEnum read(final JsonReader jsonReader) throws IOException { public static final String SERIALIZED_NAME_WORKS = "works"; @SerializedName(SERIALIZED_NAME_WORKS) - private List works; + private Set works; public WorkFlowDefinitionResponseDTO() { } @@ -266,6 +270,25 @@ public void setFallbackWorkflow(String fallbackWorkflow) { this.fallbackWorkflow = fallbackWorkflow; } + public WorkFlowDefinitionResponseDTO cronExpression(String cronExpression) { + + this.cronExpression = cronExpression; + return this; + } + + /** + * Get cronExpression + * @return cronExpression + **/ + @javax.annotation.Nullable + public String getCronExpression() { + return cronExpression; + } + + public void setCronExpression(String cronExpression) { + this.cronExpression = cronExpression; + } + public WorkFlowDefinitionResponseDTO id(UUID id) { this.id = id; @@ -407,7 +430,7 @@ public void setType(TypeEnum type) { this.type = type; } - public WorkFlowDefinitionResponseDTO works(List works) { + public WorkFlowDefinitionResponseDTO works(Set works) { this.works = works; return this; @@ -415,7 +438,7 @@ public WorkFlowDefinitionResponseDTO works(List works public WorkFlowDefinitionResponseDTO addWorksItem(WorkDefinitionResponseDTO worksItem) { if (this.works == null) { - this.works = new ArrayList<>(); + this.works = new LinkedHashSet<>(); } this.works.add(worksItem); return this; @@ -426,11 +449,11 @@ public WorkFlowDefinitionResponseDTO addWorksItem(WorkDefinitionResponseDTO work * @return works **/ @javax.annotation.Nullable - public List getWorks() { + public Set getWorks() { return works; } - public void setWorks(List works) { + public void setWorks(Set works) { this.works = works; } @@ -445,6 +468,7 @@ public boolean equals(Object o) { WorkFlowDefinitionResponseDTO workFlowDefinitionResponseDTO = (WorkFlowDefinitionResponseDTO) o; return Objects.equals(this.author, workFlowDefinitionResponseDTO.author) && Objects.equals(this.createDate, workFlowDefinitionResponseDTO.createDate) + && Objects.equals(this.cronExpression, workFlowDefinitionResponseDTO.cronExpression) && Objects.equals(this.fallbackWorkflow, workFlowDefinitionResponseDTO.fallbackWorkflow) && Objects.equals(this.id, workFlowDefinitionResponseDTO.id) && Objects.equals(this.modifyDate, workFlowDefinitionResponseDTO.modifyDate) @@ -458,8 +482,8 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(author, createDate, fallbackWorkflow, id, modifyDate, name, parameters, processingType, - properties, type, works); + return Objects.hash(author, createDate, cronExpression, id, modifyDate, name, parameters, processingType, + properties, rollbackWorkflow, type, works); } @Override @@ -469,6 +493,7 @@ public String toString() { sb.append(" author: ").append(toIndentedString(author)).append("\n"); sb.append(" createDate: ").append(toIndentedString(createDate)).append("\n"); sb.append(" fallbackWorkflow: ").append(toIndentedString(fallbackWorkflow)).append("\n"); + sb.append(" cronExpression: ").append(toIndentedString(cronExpression)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" modifyDate: ").append(toIndentedString(modifyDate)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); @@ -501,6 +526,7 @@ private String toIndentedString(Object o) { openapiFields = new HashSet(); openapiFields.add("author"); openapiFields.add("createDate"); + openapiFields.add("cronExpression"); openapiFields.add("fallbackWorkflow"); openapiFields.add("id"); openapiFields.add("modifyDate"); @@ -552,6 +578,12 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { String.format("Expected the field `author` to be a primitive type in the JSON string but got `%s`", jsonObj.get("author").toString())); } + if ((jsonObj.get("cronExpression") != null && !jsonObj.get("cronExpression").isJsonNull()) + && !jsonObj.get("cronExpression").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format( + "Expected the field `cronExpression` to be a primitive type in the JSON string but got `%s`", + jsonObj.get("cronExpression").toString())); + } if ((jsonObj.get("fallbackWorkflow") != null && !jsonObj.get("fallbackWorkflow").isJsonNull()) && !jsonObj.get("fallbackWorkflow").isJsonPrimitive()) { throw new IllegalArgumentException(String.format( diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkRequestDTO.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkRequestDTO.java index 2ca535404..1d61e8607 100644 --- a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkRequestDTO.java +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkRequestDTO.java @@ -52,7 +52,9 @@ public enum TypeEnum { TASK("TASK"), - WORKFLOW("WORKFLOW"); + WORKFLOW("WORKFLOW"), + + CHECKER("CHECKER"); private String value; diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkStatusResponseDTO.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkStatusResponseDTO.java index 178b3ce03..060937baf 100644 --- a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkStatusResponseDTO.java +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkStatusResponseDTO.java @@ -124,7 +124,9 @@ public enum TypeEnum { TASK("TASK"), - WORKFLOW("WORKFLOW"); + WORKFLOW("WORKFLOW"), + + CHECKER("CHECKER"); private String value; diff --git a/workflow-service/generated/openapi/openapi.json b/workflow-service/generated/openapi/openapi.json index fe12e9c1b..f5ce93135 100644 --- a/workflow-service/generated/openapi/openapi.json +++ b/workflow-service/generated/openapi/openapi.json @@ -1688,7 +1688,7 @@ }, "workType" : { "type" : "string", - "enum" : [ "TASK", "WORKFLOW" ] + "enum" : [ "TASK", "WORKFLOW", "CHECKER" ] }, "works" : { "type" : "array", @@ -1729,6 +1729,9 @@ "type" : "string", "format" : "date-time" }, + "cronExpression" : { + "type" : "string" + }, "fallbackWorkflow" : { "type" : "string" }, @@ -1764,6 +1767,7 @@ "enum" : [ "ASSESSMENT", "CHECKER", "INFRASTRUCTURE", "ESCALATION" ] }, "works" : { + "uniqueItems" : true, "type" : "array", "items" : { "$ref" : "#/components/schemas/WorkDefinitionResponseDTO" @@ -2006,7 +2010,7 @@ }, "type" : { "type" : "string", - "enum" : [ "TASK", "WORKFLOW" ] + "enum" : [ "TASK", "WORKFLOW", "CHECKER" ] }, "workName" : { "type" : "string" @@ -2037,7 +2041,7 @@ }, "type" : { "type" : "string", - "enum" : [ "TASK", "WORKFLOW" ] + "enum" : [ "TASK", "WORKFLOW", "CHECKER" ] }, "works" : { "type" : "array", diff --git a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkDefinitionResponseDTO.java b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkDefinitionResponseDTO.java index 26b4016b5..5b635e459 100644 --- a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkDefinitionResponseDTO.java +++ b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkDefinitionResponseDTO.java @@ -15,15 +15,17 @@ */ package com.redhat.parodos.workflow.definition.dto; -import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.type.TypeReference; +import com.redhat.parodos.workflow.definition.entity.WorkFlowCheckerMappingDefinition; import com.redhat.parodos.workflow.definition.entity.WorkFlowDefinition; import com.redhat.parodos.workflow.definition.entity.WorkFlowTaskDefinition; import com.redhat.parodos.workflow.definition.entity.WorkFlowWorkDefinition; @@ -61,12 +63,15 @@ public class WorkDefinitionResponseDTO { private String author; - private List works; + private Set works; private Map> parameters; private List outputs; + @JsonIgnore + private UUID checkerWorkId; + @JsonIgnore private Integer numberOfWorkUnits; @@ -87,15 +92,26 @@ public WorkDefinitionResponseDTOBuilder parameterFromString(String parameters) { public static WorkDefinitionResponseDTO fromWorkFlowDefinitionEntity(WorkFlowDefinition wd, List dependencies) { return WorkDefinitionResponseDTO.builder().id(wd.getId()).workType(WorkType.WORKFLOW).name(wd.getName()) - .parameterFromString(wd.getParameters()).processingType(wd.getProcessingType()).works(new ArrayList<>()) + .parameterFromString(wd.getParameters()).processingType(wd.getProcessingType()).works(new HashSet<>()) .numberOfWorkUnits(dependencies.size()).build(); } public static WorkDefinitionResponseDTO fromWorkFlowTaskDefinition(WorkFlowTaskDefinition wdt) { - return WorkDefinitionResponseDTO.builder().id(wdt.getId()).workType(WorkType.TASK).name(wdt.getName()) - .parameterFromString(wdt.getParameters()) + WorkDefinitionResponseDTOBuilder builder = WorkDefinitionResponseDTO.builder().id(wdt.getId()) + .workType(WorkType.TASK).name(wdt.getName()).parameterFromString(wdt.getParameters()) .outputs(WorkFlowDTOUtil.readStringAsObject(wdt.getOutputs(), new TypeReference<>() { - }, List.of())).build(); + }, List.of())).numberOfWorkUnits(0); + + if (wdt.getWorkFlowCheckerMappingDefinition() != null) { + builder = builder.checkerWorkId(wdt.getWorkFlowCheckerMappingDefinition().getId()); + } + + return builder.build(); + } + + public static WorkDefinitionResponseDTO fromWorkFlowCheckerMappingDefinition(WorkFlowCheckerMappingDefinition wcd) { + return WorkDefinitionResponseDTO.builder().workType(WorkType.CHECKER).numberOfWorkUnits(wcd.getTasks().size()) + .checkerWorkId(wcd.getCheckWorkFlow().getCheckerWorkFlowDefinition().getId()).build(); } } diff --git a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkFlowDefinitionResponseDTO.java b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkFlowDefinitionResponseDTO.java index d109a7d5c..7ec99ae3b 100644 --- a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkFlowDefinitionResponseDTO.java +++ b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkFlowDefinitionResponseDTO.java @@ -16,9 +16,9 @@ package com.redhat.parodos.workflow.definition.dto; import java.util.Date; -import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import com.fasterxml.jackson.annotation.JsonInclude; @@ -68,11 +68,14 @@ public class WorkFlowDefinitionResponseDTO { private WorkFlowPropertiesDefinitionDTO properties; @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List works; + private Set works; @JsonInclude(JsonInclude.Include.NON_NULL) private String fallbackWorkflow; + @JsonInclude(JsonInclude.Include.NON_NULL) + private String cronExpression; + public static class WorkFlowDefinitionResponseDTOBuilder { public WorkFlowDefinitionResponseDTOBuilder parameterFromString(String parameters) { @@ -88,15 +91,20 @@ public WorkFlowDefinitionResponseDTOBuilder parameterFromString(String parameter } public static WorkFlowDefinitionResponseDTO fromEntity(WorkFlowDefinition workFlowDefinition, - List works) { - return WorkFlowDefinitionResponseDTO.builder().id(workFlowDefinition.getId()).name(workFlowDefinition.getName()) + Set works) { + WorkFlowDefinitionResponseDTOBuilder builder = WorkFlowDefinitionResponseDTO.builder() + .id(workFlowDefinition.getId()).name(workFlowDefinition.getName()) .properties(WorkFlowPropertiesDefinitionDTO.fromEntity(workFlowDefinition.getProperties())) .parameterFromString(workFlowDefinition.getParameters()).author(workFlowDefinition.getAuthor()) .createDate(workFlowDefinition.getCreateDate()).modifyDate(workFlowDefinition.getModifyDate()) .type(workFlowDefinition.getType()).processingType(workFlowDefinition.getProcessingType()).works(works) .fallbackWorkflow(Optional.ofNullable(workFlowDefinition.getFallbackWorkFlowDefinition()) - .map(WorkFlowDefinition::getName).orElse(null)) - .build(); + .map(WorkFlowDefinition::getName).orElse(null)); + + if (workFlowDefinition.getCheckerWorkFlowDefinition() != null) { + builder = builder.cronExpression(workFlowDefinition.getCheckerWorkFlowDefinition().getCronExpression()); + } + return builder.build(); } } \ No newline at end of file diff --git a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImpl.java b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImpl.java index 5522d3d36..9a9b8944a 100644 --- a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImpl.java +++ b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImpl.java @@ -19,11 +19,14 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Queue; +import java.util.Set; import java.util.UUID; -import java.util.concurrent.CopyOnWriteArrayList; import com.fasterxml.jackson.core.type.TypeReference; import com.redhat.parodos.common.entity.AbstractEntity; @@ -263,8 +266,11 @@ public WorkFlowDefinition getParentWorkFlowByWorkName(String workName) { .map(WorkFlowWorkDefinition::getWorkFlowDefinition).orElse(null); } - private void getWorksFromWorkDefinition(List workFlowWorkDefinitions, - CopyOnWriteArrayList responseDTOs) { + private void getWorksFromWorkDefinition(WorkDefinitionResponseDTO workflow, + List workFlowWorkDefinitions, Queue responseDTOs) { + if (workflow.getWorks() == null) { + workflow.setWorks(new HashSet<>()); + } workFlowWorkDefinitions.forEach(workFlowWorkDefinition -> { WorkType workType = workFlowWorkDefinition.getWorkDefinitionType(); @@ -280,7 +286,22 @@ private void getWorksFromWorkDefinition(List workFlowWor + workFlowWorkDefinition.getWorkDefinitionId()); return; } - responseDTOs.add(WorkDefinitionResponseDTO.fromWorkFlowTaskDefinition(wdt.get())); + WorkDefinitionResponseDTO work = WorkDefinitionResponseDTO.fromWorkFlowTaskDefinition(wdt.get()); + workflow.getWorks().add(work); + responseDTOs.add(work); + } + case CHECKER -> { + Optional wcd = workFlowCheckerMappingDefinitionRepository + .findById(workFlowWorkDefinition.getWorkDefinitionId()); + if (wcd.isEmpty()) { + log.error("Cannot find the checker definition with id " + + workFlowWorkDefinition.getWorkDefinitionId()); + return; + } + WorkDefinitionResponseDTO work = WorkDefinitionResponseDTO + .fromWorkFlowCheckerMappingDefinition(wcd.get()); + workflow.getWorks().add(work); + responseDTOs.add(work); } case WORKFLOW -> { Optional wd = workFlowDefinitionRepository @@ -292,8 +313,10 @@ private void getWorksFromWorkDefinition(List workFlowWor } List wdWorkFlowWorkDependencies = workFlowWorkRepository .findByWorkFlowDefinitionIdOrderByCreateDateAsc(wd.get().getId()); - responseDTOs.add(WorkDefinitionResponseDTO.fromWorkFlowDefinitionEntity(wd.get(), - wdWorkFlowWorkDependencies)); + WorkDefinitionResponseDTO work = WorkDefinitionResponseDTO.fromWorkFlowDefinitionEntity(wd.get(), + wdWorkFlowWorkDependencies); + workflow.getWorks().add(work); + responseDTOs.add(work); } default -> { } @@ -302,51 +325,65 @@ private void getWorksFromWorkDefinition(List workFlowWor } - private List buildWorkFlowWorksDTOs(WorkFlowDefinition workFlowDefinition, + private Set buildWorkFlowWorksDTOs(WorkFlowDefinition workFlowDefinition, List workFlowWorkDefinitions) { - CopyOnWriteArrayList workDefinitionResponseDTOs = new CopyOnWriteArrayList<>(); - Map workFlowWorksStartIndex = new HashMap<>(); + Queue workDefinitionResponseDTOs = new LinkedList<>(); + WorkDefinitionResponseDTO rootWorkFlow = buildRootWorkFlow(workFlowDefinition, workFlowWorkDefinitions, + workDefinitionResponseDTOs); + + // fill in subsequent workUnits + // workDefinitionResponseDTOs.size() will grow as long as there are new works + populateWorkFlowWorksRecursive(workDefinitionResponseDTOs); - // add workflow - workDefinitionResponseDTOs - .add(WorkDefinitionResponseDTO.builder().id(workFlowDefinition.getId()).workType(WorkType.WORKFLOW) - .name(workFlowDefinition.getName()).parameterFromString(workFlowDefinition.getParameters()) - .processingType(workFlowDefinition.getProcessingType()).works(new ArrayList<>()) - .numberOfWorkUnits(workFlowWorkDefinitions.size()).build()); - workFlowWorksStartIndex.put(workFlowDefinition.getName(), 1); + return rootWorkFlow.getWorks(); + } + private WorkDefinitionResponseDTO buildRootWorkFlow(WorkFlowDefinition workFlowDefinition, + List workFlowWorkDefinitions, + Queue workDefinitionResponseDTOs) { + WorkDefinitionResponseDTO rootWorkFlow = WorkDefinitionResponseDTO.builder().id(workFlowDefinition.getId()) + .workType(workFlowDefinition.getType() == WorkFlowType.CHECKER ? WorkType.CHECKER : WorkType.WORKFLOW) + .name(workFlowDefinition.getName()).parameterFromString(workFlowDefinition.getParameters()) + .processingType(workFlowDefinition.getProcessingType()).works(new HashSet<>()) + .numberOfWorkUnits(workFlowWorkDefinitions.size()).build(); + workDefinitionResponseDTOs.add(rootWorkFlow); // add workflowWorkUnits - this.getWorksFromWorkDefinition(workFlowWorkDefinitions, workDefinitionResponseDTOs); + this.getWorksFromWorkDefinition(rootWorkFlow, workFlowWorkDefinitions, workDefinitionResponseDTOs); - // fill in subsequent workUnits - // this responseSize is like this because we modify the size of the - // workDefinitionResponseDTO - for (int i = 1; i < workDefinitionResponseDTOs.size(); i++) { - if (workDefinitionResponseDTOs.get(i).getWorkType() == WorkType.WORKFLOW) { - workFlowWorksStartIndex.put(workDefinitionResponseDTOs.get(i).getName(), - workDefinitionResponseDTOs.size()); - - List workFlowWorkUnits1Definition = workFlowWorkRepository - .findByWorkFlowDefinitionIdOrderByCreateDateAsc(workDefinitionResponseDTOs.get(i).getId()) - .stream().sorted(Comparator.comparing(WorkFlowWorkDefinition::getCreateDate)).toList(); - this.getWorksFromWorkDefinition(workFlowWorkUnits1Definition, workDefinitionResponseDTOs); - } + return rootWorkFlow; + } + + private void populateWorkFlowWorksRecursive(Queue workDefinitionResponseDTOs) { + if (workDefinitionResponseDTOs.isEmpty()) { + return; } + WorkDefinitionResponseDTO workflow = workDefinitionResponseDTOs.poll(); + List workFlowWorkUnitsDefinition = workFlowWorkRepository + .findByWorkFlowDefinitionIdOrderByCreateDateAsc(workflow.getId()).stream() + .sorted(Comparator.comparing(WorkFlowWorkDefinition::getCreateDate)).toList(); - for (int j = workDefinitionResponseDTOs.size() - 1; j >= 0; j--) { - if (workDefinitionResponseDTOs.get(j).getWorkType() == WorkType.WORKFLOW) { - List tmpList = new ArrayList<>(); - for (int k = workFlowWorksStartIndex.get(workDefinitionResponseDTOs.get(j) - .getName()); k < workFlowWorksStartIndex.get(workDefinitionResponseDTOs.get(j).getName()) - + workDefinitionResponseDTOs.get(j).getNumberOfWorkUnits() - && k < workDefinitionResponseDTOs.size(); k++) { + this.getWorksFromWorkDefinition(workflow, workFlowWorkUnitsDefinition, workDefinitionResponseDTOs); + this.getCheckerWorkFromWorkDefinition(workflow, workDefinitionResponseDTOs); + populateWorkFlowWorksRecursive(workDefinitionResponseDTOs); + } - tmpList.add(workDefinitionResponseDTOs.get(k)); - } - workDefinitionResponseDTOs.get(j).setWorks(tmpList); + private void getCheckerWorkFromWorkDefinition(WorkDefinitionResponseDTO workflow, + Queue workDefinitionResponseDTOs) { + if (workflow.getCheckerWorkId() != null) { + WorkFlowDefinition checkerWorkflowDefinition = workFlowCheckerMappingDefinitionRepository + .findById(workflow.getCheckerWorkId()).get().getCheckWorkFlow(); + WorkDefinitionResponseDTO checkerWorkflowDefinitionDTO = WorkDefinitionResponseDTO.builder() + .id(checkerWorkflowDefinition.getId()).workType(WorkType.CHECKER) + .name(checkerWorkflowDefinition.getName()) + .parameterFromString(checkerWorkflowDefinition.getParameters()) + .processingType(checkerWorkflowDefinition.getProcessingType()).works(new HashSet<>()) + .numberOfWorkUnits(checkerWorkflowDefinition.getNumberOfWorks()).build(); + workDefinitionResponseDTOs.add(checkerWorkflowDefinitionDTO); + if (workflow.getWorks() == null) { + workflow.setWorks(new HashSet<>()); } + workflow.getWorks().add(checkerWorkflowDefinitionDTO); } - return workDefinitionResponseDTOs.get(0).getWorks(); } public void cleanAllDefinitionMappings() { diff --git a/workflow-service/src/test/java/com/redhat/parodos/workflow/WorkFlowDelegateTest.java b/workflow-service/src/test/java/com/redhat/parodos/workflow/WorkFlowDelegateTest.java index 2a8364760..41f9099f2 100644 --- a/workflow-service/src/test/java/com/redhat/parodos/workflow/WorkFlowDelegateTest.java +++ b/workflow-service/src/test/java/com/redhat/parodos/workflow/WorkFlowDelegateTest.java @@ -17,6 +17,7 @@ import java.util.HashMap; import java.util.List; +import java.util.Set; import java.util.UUID; import com.fasterxml.jackson.core.type.TypeReference; @@ -115,8 +116,8 @@ private WorkFlowDefinitionResponseDTO sampleWorkflowDefinitionResponse() { return WorkFlowDefinitionResponseDTO .builder().name( TEST_WORKFLOW_NAME) - .works(List.of(WorkDefinitionResponseDTO.builder().name(TEST_SUB_WORKFLOW_NAME) - .workType(WorkType.WORKFLOW).works(List.of(WorkDefinitionResponseDTO.builder() + .works(Set.of(WorkDefinitionResponseDTO.builder().name(TEST_SUB_WORKFLOW_NAME) + .workType(WorkType.WORKFLOW).works(Set.of(WorkDefinitionResponseDTO.builder() .name(TEST_TASK_NAME).workType(WorkType.TASK).build())) .build())) .build(); diff --git a/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/controller/WorkFlowDefinitionControllerTest.java b/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/controller/WorkFlowDefinitionControllerTest.java index bffd16812..d22c25fd1 100644 --- a/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/controller/WorkFlowDefinitionControllerTest.java +++ b/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/controller/WorkFlowDefinitionControllerTest.java @@ -1,6 +1,7 @@ package com.redhat.parodos.workflow.definition.controller; import java.util.List; +import java.util.Set; import java.util.UUID; import com.redhat.parodos.ControllerMockClient; @@ -167,7 +168,7 @@ private WorkFlowDefinitionResponseDTO createSampleWorkFlowDefinition(String name WorkFlowDefinitionResponseDTO workFlowDefinitionResponseDTO = new WorkFlowDefinitionResponseDTO(); workFlowDefinitionResponseDTO.setName(name); workFlowDefinitionResponseDTO.setId(UUID.randomUUID()); - workFlowDefinitionResponseDTO.setWorks(List.of(createSampleWorkFlowTaskDefinition("task1"))); + workFlowDefinitionResponseDTO.setWorks(Set.of(createSampleWorkFlowTaskDefinition("task1"))); return workFlowDefinitionResponseDTO; } diff --git a/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImplTest.java b/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImplTest.java index 3df0ac6d0..18665dc6a 100644 --- a/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImplTest.java +++ b/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImplTest.java @@ -24,6 +24,7 @@ import java.util.UUID; import com.redhat.parodos.common.exceptions.ResourceNotFoundException; +import com.redhat.parodos.workflow.definition.dto.WorkDefinitionResponseDTO; import com.redhat.parodos.workflow.definition.dto.WorkFlowCheckerDTO; import com.redhat.parodos.workflow.definition.dto.WorkFlowDefinitionResponseDTO; import com.redhat.parodos.workflow.definition.entity.WorkFlowCheckerMappingDefinition; @@ -53,6 +54,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; @@ -248,10 +250,11 @@ public void getWorkFlowDefinitionByNameWithMasterWorkflow() { verify(this.workFlowDefinitionRepository, times(1)).findFirstByName(any()); when(this.workFlowDefinitionRepository.findFirstByName(any())).thenReturn(sampleWorkFlowDefinition(TEST)); - + Optional firstWork = result.getWorks().stream().findFirst(); + assertTrue(firstWork.isPresent()); assertEquals(result.getWorks().size(), 1); - assertEquals(result.getWorks().get(0).getName(), "SubWorkFlow"); - assertEquals(result.getWorks().get(0).getWorkType(), WorkType.WORKFLOW); + assertEquals(firstWork.get().getName(), "SubWorkFlow"); + assertEquals(firstWork.get().getWorkType(), WorkType.WORKFLOW); } @Test diff --git a/workflow-service/src/test/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImplTest.java b/workflow-service/src/test/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImplTest.java index 54ae91d17..45f42e92b 100644 --- a/workflow-service/src/test/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImplTest.java +++ b/workflow-service/src/test/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImplTest.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import com.redhat.parodos.common.exceptions.IllegalWorkFlowStateException; @@ -164,7 +165,7 @@ void executeWithDTOWithValidData() { workFlowExecution.setId(UUID.randomUUID()); when(this.workFlowRepository.save(any())).thenReturn(workFlowExecution); WorkFlowDefinitionResponseDTO workFlowDefinitionResponseDTO = WorkFlowDefinitionResponseDTO.builder() - .name(TEST_WORKFLOW_NAME).works(List.of()).build(); + .name(TEST_WORKFLOW_NAME).works(Set.of()).build(); when(this.workFlowDefinitionService.getWorkFlowDefinitionByName(TEST_WORKFLOW_NAME)) .thenReturn(workFlowDefinitionResponseDTO); when(this.userService.getUserEntityByUsername("test-user")).thenReturn(user); @@ -206,7 +207,7 @@ void executeWithDTOWithMissingInvokingExecutionContext() { UUID invokingExecutionId = UUID.randomUUID(); when(this.workFlowRepository.findById(invokingExecutionId)).thenReturn(Optional.empty()); WorkFlowDefinitionResponseDTO workFlowDefinitionResponseDTO = WorkFlowDefinitionResponseDTO.builder() - .name(TEST_WORKFLOW_NAME).works(List.of()).build(); + .name(TEST_WORKFLOW_NAME).works(Set.of()).build(); when(this.workFlowDefinitionService.getWorkFlowDefinitionByName(TEST_WORKFLOW_NAME)) .thenReturn(workFlowDefinitionResponseDTO); when(this.userService.getUserEntityByUsername("test-user")).thenReturn(user); @@ -264,7 +265,7 @@ void executeWithDTOWithEmptyInvokingExecutionContext() { // @formatter:on when(this.workFlowRepository.findById(invokingExecutionId)).thenReturn(Optional.of(invokingWorkFlowExecution)); WorkFlowDefinitionResponseDTO workFlowDefinitionResponseDTO = WorkFlowDefinitionResponseDTO.builder() - .name(TEST_WORKFLOW_NAME).works(List.of()).build(); + .name(TEST_WORKFLOW_NAME).works(Set.of()).build(); when(this.workFlowDefinitionService.getWorkFlowDefinitionByName(TEST_WORKFLOW_NAME)) .thenReturn(workFlowDefinitionResponseDTO); when(this.userService.getUserEntityByUsername("test-user")).thenReturn(user); @@ -331,7 +332,7 @@ void executeWithDTOWithInvokingExecutionContext() { // @formatter:on when(this.workFlowRepository.findById(invokingExecutionId)).thenReturn(Optional.of(invokingWorkFlowExecution)); WorkFlowDefinitionResponseDTO workFlowDefinitionResponseDTO = WorkFlowDefinitionResponseDTO.builder() - .name(TEST_WORKFLOW_NAME).works(List.of()).build(); + .name(TEST_WORKFLOW_NAME).works(Set.of()).build(); when(this.workFlowDefinitionService.getWorkFlowDefinitionByName(TEST_WORKFLOW_NAME)) .thenReturn(workFlowDefinitionResponseDTO); when(this.userService.getUserEntityByUsername("test-user")).thenReturn(user); From 063958fbcc1083392825ecc537b0bbf7489f152f Mon Sep 17 00:00:00 2001 From: gabriel-farache Date: Mon, 3 Jul 2023 14:55:55 +0200 Subject: [PATCH 2/2] Add test and changed list of works to sorted set of works --- workflow-service-sdk/api/openapi.yaml | 15 ++- .../docs/WorkDefinitionResponseDTO.md | 2 + .../sdk/model/WorkDefinitionResponseDTO.java | 72 +++++++++++++- .../model/WorkFlowDefinitionResponseDTO.java | 48 +++++----- .../generated/openapi/openapi.json | 8 ++ .../dto/WorkDefinitionResponseDTO.java | 25 +++-- .../WorkFlowTaskDefinitionDTOConverter.java | 9 +- .../WorkFlowDefinitionServiceImpl.java | 41 ++++---- .../workflow/WorkFlowDelegateTest.java | 17 ++-- .../WorkFlowDefinitionServiceImplTest.java | 96 ++++++++++++++++++- 10 files changed, 258 insertions(+), 75 deletions(-) diff --git a/workflow-service-sdk/api/openapi.yaml b/workflow-service-sdk/api/openapi.yaml index 75b725138..84282ff4d 100644 --- a/workflow-service-sdk/api/openapi.yaml +++ b/workflow-service-sdk/api/openapi.yaml @@ -1242,10 +1242,12 @@ components: type: object WorkDefinitionResponseDTO: example: + cronExpression: cronExpression outputs: - EXCEPTION - EXCEPTION processingType: SEQUENTIAL + workFlowCheckerMappingDefinitionId: 046b6c7f-0b8a-43b9-b35d-6489e6daee91 works: - null - null @@ -1259,6 +1261,8 @@ components: properties: author: type: string + cronExpression: + type: string id: format: uuid type: string @@ -1285,6 +1289,9 @@ components: - PARALLEL - OTHER type: string + workFlowCheckerMappingDefinitionId: + format: uuid + type: string workType: enum: - TASK @@ -1420,10 +1427,12 @@ components: cronExpression: cronExpression processingType: SEQUENTIAL works: - - outputs: + - cronExpression: cronExpression + outputs: - EXCEPTION - EXCEPTION processingType: SEQUENTIAL + workFlowCheckerMappingDefinitionId: 046b6c7f-0b8a-43b9-b35d-6489e6daee91 works: - null - null @@ -1434,10 +1443,12 @@ components: parameters: key: key: "{}" - - outputs: + - cronExpression: cronExpression + outputs: - EXCEPTION - EXCEPTION processingType: SEQUENTIAL + workFlowCheckerMappingDefinitionId: 046b6c7f-0b8a-43b9-b35d-6489e6daee91 works: - null - null diff --git a/workflow-service-sdk/docs/WorkDefinitionResponseDTO.md b/workflow-service-sdk/docs/WorkDefinitionResponseDTO.md index 3faa8d2df..0c450c173 100644 --- a/workflow-service-sdk/docs/WorkDefinitionResponseDTO.md +++ b/workflow-service-sdk/docs/WorkDefinitionResponseDTO.md @@ -8,11 +8,13 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| |**author** | **String** | | [optional] | +|**cronExpression** | **String** | | [optional] | |**id** | **UUID** | | [optional] | |**name** | **String** | | [optional] | |**outputs** | [**List<OutputsEnum>**](#List<OutputsEnum>) | | [optional] | |**parameters** | **Map<String, Map<String, Object>>** | | [optional] | |**processingType** | [**ProcessingTypeEnum**](#ProcessingTypeEnum) | | [optional] | +|**workFlowCheckerMappingDefinitionId** | **UUID** | | [optional] | |**workType** | [**WorkTypeEnum**](#WorkTypeEnum) | | [optional] | |**works** | [**Set<WorkDefinitionResponseDTO>**](WorkDefinitionResponseDTO.md) | | [optional] | diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkDefinitionResponseDTO.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkDefinitionResponseDTO.java index e33a05d7d..49506d146 100644 --- a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkDefinitionResponseDTO.java +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkDefinitionResponseDTO.java @@ -48,6 +48,11 @@ public class WorkDefinitionResponseDTO { @SerializedName(SERIALIZED_NAME_AUTHOR) private String author; + public static final String SERIALIZED_NAME_CRON_EXPRESSION = "cronExpression"; + + @SerializedName(SERIALIZED_NAME_CRON_EXPRESSION) + private String cronExpression; + public static final String SERIALIZED_NAME_ID = "id"; @SerializedName(SERIALIZED_NAME_ID) @@ -181,6 +186,11 @@ public ProcessingTypeEnum read(final JsonReader jsonReader) throws IOException { @SerializedName(SERIALIZED_NAME_PROCESSING_TYPE) private ProcessingTypeEnum processingType; + public static final String SERIALIZED_NAME_WORK_FLOW_CHECKER_MAPPING_DEFINITION_ID = "workFlowCheckerMappingDefinitionId"; + + @SerializedName(SERIALIZED_NAME_WORK_FLOW_CHECKER_MAPPING_DEFINITION_ID) + private UUID workFlowCheckerMappingDefinitionId; + /** * Gets or Sets workType */ @@ -266,6 +276,25 @@ public void setAuthor(String author) { this.author = author; } + public WorkDefinitionResponseDTO cronExpression(String cronExpression) { + + this.cronExpression = cronExpression; + return this; + } + + /** + * Get cronExpression + * @return cronExpression + **/ + @javax.annotation.Nullable + public String getCronExpression() { + return cronExpression; + } + + public void setCronExpression(String cronExpression) { + this.cronExpression = cronExpression; + } + public WorkDefinitionResponseDTO id(UUID id) { this.id = id; @@ -377,6 +406,25 @@ public void setProcessingType(ProcessingTypeEnum processingType) { this.processingType = processingType; } + public WorkDefinitionResponseDTO workFlowCheckerMappingDefinitionId(UUID workFlowCheckerMappingDefinitionId) { + + this.workFlowCheckerMappingDefinitionId = workFlowCheckerMappingDefinitionId; + return this; + } + + /** + * Get workFlowCheckerMappingDefinitionId + * @return workFlowCheckerMappingDefinitionId + **/ + @javax.annotation.Nullable + public UUID getWorkFlowCheckerMappingDefinitionId() { + return workFlowCheckerMappingDefinitionId; + } + + public void setWorkFlowCheckerMappingDefinitionId(UUID workFlowCheckerMappingDefinitionId) { + this.workFlowCheckerMappingDefinitionId = workFlowCheckerMappingDefinitionId; + } + public WorkDefinitionResponseDTO workType(WorkTypeEnum workType) { this.workType = workType; @@ -433,18 +481,22 @@ public boolean equals(Object o) { } WorkDefinitionResponseDTO workDefinitionResponseDTO = (WorkDefinitionResponseDTO) o; return Objects.equals(this.author, workDefinitionResponseDTO.author) + && Objects.equals(this.cronExpression, workDefinitionResponseDTO.cronExpression) && Objects.equals(this.id, workDefinitionResponseDTO.id) && Objects.equals(this.name, workDefinitionResponseDTO.name) && Objects.equals(this.outputs, workDefinitionResponseDTO.outputs) && Objects.equals(this.parameters, workDefinitionResponseDTO.parameters) && Objects.equals(this.processingType, workDefinitionResponseDTO.processingType) + && Objects.equals(this.workFlowCheckerMappingDefinitionId, + workDefinitionResponseDTO.workFlowCheckerMappingDefinitionId) && Objects.equals(this.workType, workDefinitionResponseDTO.workType) && Objects.equals(this.works, workDefinitionResponseDTO.works); } @Override public int hashCode() { - return Objects.hash(author, id, name, outputs, parameters, processingType, workType, works); + return Objects.hash(author, cronExpression, id, name, outputs, parameters, processingType, + workFlowCheckerMappingDefinitionId, workType, works); } @Override @@ -452,11 +504,14 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class WorkDefinitionResponseDTO {\n"); sb.append(" author: ").append(toIndentedString(author)).append("\n"); + sb.append(" cronExpression: ").append(toIndentedString(cronExpression)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" outputs: ").append(toIndentedString(outputs)).append("\n"); sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); sb.append(" processingType: ").append(toIndentedString(processingType)).append("\n"); + sb.append(" workFlowCheckerMappingDefinitionId: ") + .append(toIndentedString(workFlowCheckerMappingDefinitionId)).append("\n"); sb.append(" workType: ").append(toIndentedString(workType)).append("\n"); sb.append(" works: ").append(toIndentedString(works)).append("\n"); sb.append("}"); @@ -482,11 +537,13 @@ private String toIndentedString(Object o) { // a set of all properties/fields (JSON key names) openapiFields = new HashSet(); openapiFields.add("author"); + openapiFields.add("cronExpression"); openapiFields.add("id"); openapiFields.add("name"); openapiFields.add("outputs"); openapiFields.add("parameters"); openapiFields.add("processingType"); + openapiFields.add("workFlowCheckerMappingDefinitionId"); openapiFields.add("workType"); openapiFields.add("works"); @@ -530,6 +587,12 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { String.format("Expected the field `author` to be a primitive type in the JSON string but got `%s`", jsonObj.get("author").toString())); } + if ((jsonObj.get("cronExpression") != null && !jsonObj.get("cronExpression").isJsonNull()) + && !jsonObj.get("cronExpression").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format( + "Expected the field `cronExpression` to be a primitive type in the JSON string but got `%s`", + jsonObj.get("cronExpression").toString())); + } if ((jsonObj.get("id") != null && !jsonObj.get("id").isJsonNull()) && !jsonObj.get("id").isJsonPrimitive()) { throw new IllegalArgumentException( String.format("Expected the field `id` to be a primitive type in the JSON string but got `%s`", @@ -553,6 +616,13 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { "Expected the field `processingType` to be a primitive type in the JSON string but got `%s`", jsonObj.get("processingType").toString())); } + if ((jsonObj.get("workFlowCheckerMappingDefinitionId") != null + && !jsonObj.get("workFlowCheckerMappingDefinitionId").isJsonNull()) + && !jsonObj.get("workFlowCheckerMappingDefinitionId").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format( + "Expected the field `workFlowCheckerMappingDefinitionId` to be a primitive type in the JSON string but got `%s`", + jsonObj.get("workFlowCheckerMappingDefinitionId").toString())); + } if ((jsonObj.get("workType") != null && !jsonObj.get("workType").isJsonNull()) && !jsonObj.get("workType").isJsonPrimitive()) { throw new IllegalArgumentException(String.format( diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowDefinitionResponseDTO.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowDefinitionResponseDTO.java index ff2947213..6464fac1b 100644 --- a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowDefinitionResponseDTO.java +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowDefinitionResponseDTO.java @@ -52,16 +52,16 @@ public class WorkFlowDefinitionResponseDTO { @SerializedName(SERIALIZED_NAME_CREATE_DATE) private Date createDate; - public static final String SERIALIZED_NAME_FALLBACK_WORKFLOW = "fallbackWorkflow"; - - @SerializedName(SERIALIZED_NAME_FALLBACK_WORKFLOW) - private String fallbackWorkflow; - public static final String SERIALIZED_NAME_CRON_EXPRESSION = "cronExpression"; @SerializedName(SERIALIZED_NAME_CRON_EXPRESSION) private String cronExpression; + public static final String SERIALIZED_NAME_FALLBACK_WORKFLOW = "fallbackWorkflow"; + + @SerializedName(SERIALIZED_NAME_FALLBACK_WORKFLOW) + private String fallbackWorkflow; + public static final String SERIALIZED_NAME_ID = "id"; @SerializedName(SERIALIZED_NAME_ID) @@ -251,42 +251,42 @@ public void setCreateDate(Date createDate) { this.createDate = createDate; } - public WorkFlowDefinitionResponseDTO fallbackWorkflow(String fallbackWorkflow) { + public WorkFlowDefinitionResponseDTO cronExpression(String cronExpression) { - this.fallbackWorkflow = fallbackWorkflow; + this.cronExpression = cronExpression; return this; } /** - * Get fallbackWorkflow - * @return fallbackWorkflow + * Get cronExpression + * @return cronExpression **/ @javax.annotation.Nullable - public String getFallbackWorkflow() { - return fallbackWorkflow; + public String getCronExpression() { + return cronExpression; } - public void setFallbackWorkflow(String fallbackWorkflow) { - this.fallbackWorkflow = fallbackWorkflow; + public void setCronExpression(String cronExpression) { + this.cronExpression = cronExpression; } - public WorkFlowDefinitionResponseDTO cronExpression(String cronExpression) { + public WorkFlowDefinitionResponseDTO fallbackWorkflow(String fallbackWorkflow) { - this.cronExpression = cronExpression; + this.fallbackWorkflow = fallbackWorkflow; return this; } /** - * Get cronExpression - * @return cronExpression + * Get fallbackWorkflow + * @return fallbackWorkflow **/ @javax.annotation.Nullable - public String getCronExpression() { - return cronExpression; + public String getFallbackWorkflow() { + return fallbackWorkflow; } - public void setCronExpression(String cronExpression) { - this.cronExpression = cronExpression; + public void setFallbackWorkflow(String fallbackWorkflow) { + this.fallbackWorkflow = fallbackWorkflow; } public WorkFlowDefinitionResponseDTO id(UUID id) { @@ -482,8 +482,8 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(author, createDate, cronExpression, id, modifyDate, name, parameters, processingType, - properties, rollbackWorkflow, type, works); + return Objects.hash(author, createDate, cronExpression, fallbackWorkflow, id, modifyDate, name, parameters, + processingType, properties, type, works); } @Override @@ -492,8 +492,8 @@ public String toString() { sb.append("class WorkFlowDefinitionResponseDTO {\n"); sb.append(" author: ").append(toIndentedString(author)).append("\n"); sb.append(" createDate: ").append(toIndentedString(createDate)).append("\n"); - sb.append(" fallbackWorkflow: ").append(toIndentedString(fallbackWorkflow)).append("\n"); sb.append(" cronExpression: ").append(toIndentedString(cronExpression)).append("\n"); + sb.append(" fallbackWorkflow: ").append(toIndentedString(fallbackWorkflow)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" modifyDate: ").append(toIndentedString(modifyDate)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); diff --git a/workflow-service/generated/openapi/openapi.json b/workflow-service/generated/openapi/openapi.json index f5ce93135..2645e3884 100644 --- a/workflow-service/generated/openapi/openapi.json +++ b/workflow-service/generated/openapi/openapi.json @@ -1659,6 +1659,9 @@ "author" : { "type" : "string" }, + "cronExpression" : { + "type" : "string" + }, "id" : { "type" : "string", "format" : "uuid" @@ -1686,11 +1689,16 @@ "type" : "string", "enum" : [ "SEQUENTIAL", "PARALLEL", "OTHER" ] }, + "workFlowCheckerMappingDefinitionId" : { + "type" : "string", + "format" : "uuid" + }, "workType" : { "type" : "string", "enum" : [ "TASK", "WORKFLOW", "CHECKER" ] }, "works" : { + "uniqueItems" : true, "type" : "array", "items" : { "$ref" : "#/components/schemas/WorkDefinitionResponseDTO" diff --git a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkDefinitionResponseDTO.java b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkDefinitionResponseDTO.java index 5b635e459..978ce5b3c 100644 --- a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkDefinitionResponseDTO.java +++ b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/WorkDefinitionResponseDTO.java @@ -15,10 +15,9 @@ */ package com.redhat.parodos.workflow.definition.dto; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.UUID; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -63,14 +62,17 @@ public class WorkDefinitionResponseDTO { private String author; - private Set works; + private LinkedHashSet works; private Map> parameters; private List outputs; - @JsonIgnore - private UUID checkerWorkId; + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private UUID workFlowCheckerMappingDefinitionId; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private String cronExpression; @JsonIgnore private Integer numberOfWorkUnits; @@ -92,8 +94,8 @@ public WorkDefinitionResponseDTOBuilder parameterFromString(String parameters) { public static WorkDefinitionResponseDTO fromWorkFlowDefinitionEntity(WorkFlowDefinition wd, List dependencies) { return WorkDefinitionResponseDTO.builder().id(wd.getId()).workType(WorkType.WORKFLOW).name(wd.getName()) - .parameterFromString(wd.getParameters()).processingType(wd.getProcessingType()).works(new HashSet<>()) - .numberOfWorkUnits(dependencies.size()).build(); + .parameterFromString(wd.getParameters()).processingType(wd.getProcessingType()) + .works(new LinkedHashSet<>()).numberOfWorkUnits(dependencies.size()).build(); } public static WorkDefinitionResponseDTO fromWorkFlowTaskDefinition(WorkFlowTaskDefinition wdt) { @@ -103,15 +105,18 @@ public static WorkDefinitionResponseDTO fromWorkFlowTaskDefinition(WorkFlowTaskD }, List.of())).numberOfWorkUnits(0); if (wdt.getWorkFlowCheckerMappingDefinition() != null) { - builder = builder.checkerWorkId(wdt.getWorkFlowCheckerMappingDefinition().getId()); + builder = builder.workFlowCheckerMappingDefinitionId(wdt.getWorkFlowCheckerMappingDefinition().getId()); } return builder.build(); } public static WorkDefinitionResponseDTO fromWorkFlowCheckerMappingDefinition(WorkFlowCheckerMappingDefinition wcd) { - return WorkDefinitionResponseDTO.builder().workType(WorkType.CHECKER).numberOfWorkUnits(wcd.getTasks().size()) - .checkerWorkId(wcd.getCheckWorkFlow().getCheckerWorkFlowDefinition().getId()).build(); + return WorkDefinitionResponseDTO.builder().id(wcd.getCheckWorkFlow().getId()) + .name(wcd.getCheckWorkFlow().getName()).parameterFromString(wcd.getCheckWorkFlow().getParameters()) + .processingType(wcd.getCheckWorkFlow().getProcessingType()).workType(WorkType.CHECKER) + .numberOfWorkUnits(wcd.getCheckWorkFlow().getNumberOfWorks()).cronExpression(wcd.getCronExpression()) + .build(); } } diff --git a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/converter/WorkFlowTaskDefinitionDTOConverter.java b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/converter/WorkFlowTaskDefinitionDTOConverter.java index 5d2b4aa88..76f55839c 100644 --- a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/converter/WorkFlowTaskDefinitionDTOConverter.java +++ b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/dto/converter/WorkFlowTaskDefinitionDTOConverter.java @@ -16,6 +16,7 @@ package com.redhat.parodos.workflow.definition.dto.converter; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import com.fasterxml.jackson.core.JsonProcessingException; @@ -35,11 +36,11 @@ */ public class WorkFlowTaskDefinitionDTOConverter - implements Converter, List> { + implements Converter, Set> { @Override - public List convert( - MappingContext, List> context) { + public Set convert( + MappingContext, Set> context) { ObjectMapper objectMapper = new ObjectMapper(); List source = context.getSource(); return source.stream().map(workFlowTaskDefinition -> { @@ -52,7 +53,7 @@ public List convert( catch (JsonProcessingException e) { throw new WorkflowDefinitionException(e); } - }).collect(Collectors.toList()); + }).collect(Collectors.toSet()); } } diff --git a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImpl.java b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImpl.java index 9a9b8944a..16dbdd982 100644 --- a/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImpl.java +++ b/workflow-service/src/main/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImpl.java @@ -19,7 +19,7 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -269,7 +269,8 @@ public WorkFlowDefinition getParentWorkFlowByWorkName(String workName) { private void getWorksFromWorkDefinition(WorkDefinitionResponseDTO workflow, List workFlowWorkDefinitions, Queue responseDTOs) { if (workflow.getWorks() == null) { - workflow.setWorks(new HashSet<>()); + // LinkedHashSet to keep insertion order + workflow.setWorks(new LinkedHashSet<>()); } workFlowWorkDefinitions.forEach(workFlowWorkDefinition -> { @@ -342,13 +343,11 @@ private WorkDefinitionResponseDTO buildRootWorkFlow(WorkFlowDefinition workFlowD List workFlowWorkDefinitions, Queue workDefinitionResponseDTOs) { WorkDefinitionResponseDTO rootWorkFlow = WorkDefinitionResponseDTO.builder().id(workFlowDefinition.getId()) - .workType(workFlowDefinition.getType() == WorkFlowType.CHECKER ? WorkType.CHECKER : WorkType.WORKFLOW) - .name(workFlowDefinition.getName()).parameterFromString(workFlowDefinition.getParameters()) - .processingType(workFlowDefinition.getProcessingType()).works(new HashSet<>()) + .workType(WorkType.WORKFLOW).name(workFlowDefinition.getName()) + .parameterFromString(workFlowDefinition.getParameters()) + .processingType(workFlowDefinition.getProcessingType()).works(new LinkedHashSet<>()) .numberOfWorkUnits(workFlowWorkDefinitions.size()).build(); workDefinitionResponseDTOs.add(rootWorkFlow); - // add workflowWorkUnits - this.getWorksFromWorkDefinition(rootWorkFlow, workFlowWorkDefinitions, workDefinitionResponseDTOs); return rootWorkFlow; } @@ -369,20 +368,22 @@ private void populateWorkFlowWorksRecursive(Queue wor private void getCheckerWorkFromWorkDefinition(WorkDefinitionResponseDTO workflow, Queue workDefinitionResponseDTOs) { - if (workflow.getCheckerWorkId() != null) { - WorkFlowDefinition checkerWorkflowDefinition = workFlowCheckerMappingDefinitionRepository - .findById(workflow.getCheckerWorkId()).get().getCheckWorkFlow(); - WorkDefinitionResponseDTO checkerWorkflowDefinitionDTO = WorkDefinitionResponseDTO.builder() - .id(checkerWorkflowDefinition.getId()).workType(WorkType.CHECKER) - .name(checkerWorkflowDefinition.getName()) - .parameterFromString(checkerWorkflowDefinition.getParameters()) - .processingType(checkerWorkflowDefinition.getProcessingType()).works(new HashSet<>()) - .numberOfWorkUnits(checkerWorkflowDefinition.getNumberOfWorks()).build(); - workDefinitionResponseDTOs.add(checkerWorkflowDefinitionDTO); - if (workflow.getWorks() == null) { - workflow.setWorks(new HashSet<>()); + if (workflow.getWorkFlowCheckerMappingDefinitionId() != null) { + Optional checkerMappingDefinition = workFlowCheckerMappingDefinitionRepository + .findById(workflow.getWorkFlowCheckerMappingDefinitionId()); + if (checkerMappingDefinition.isPresent()) { + WorkDefinitionResponseDTO checkerWorkflowDefinitionDTO = WorkDefinitionResponseDTO + .fromWorkFlowCheckerMappingDefinition(checkerMappingDefinition.get()); + workDefinitionResponseDTOs.add(checkerWorkflowDefinitionDTO); + if (workflow.getWorks() == null) { + workflow.setWorks(new LinkedHashSet<>()); + } + workflow.getWorks().add(checkerWorkflowDefinitionDTO); + } + else { + log.error("WorkFlowCheckerMappingDefinition %s associated with WorkDefinition %s not found" + .formatted(workflow.getWorkFlowCheckerMappingDefinitionId(), workflow.getId())); } - workflow.getWorks().add(checkerWorkflowDefinitionDTO); } } diff --git a/workflow-service/src/test/java/com/redhat/parodos/workflow/WorkFlowDelegateTest.java b/workflow-service/src/test/java/com/redhat/parodos/workflow/WorkFlowDelegateTest.java index 41f9099f2..ccfae3d4a 100644 --- a/workflow-service/src/test/java/com/redhat/parodos/workflow/WorkFlowDelegateTest.java +++ b/workflow-service/src/test/java/com/redhat/parodos/workflow/WorkFlowDelegateTest.java @@ -16,8 +16,8 @@ package com.redhat.parodos.workflow; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; import java.util.UUID; import com.fasterxml.jackson.core.type.TypeReference; @@ -113,14 +113,13 @@ void initWorkFlowContext_when_workflowParameterIsFound_thenReturn_success() { } private WorkFlowDefinitionResponseDTO sampleWorkflowDefinitionResponse() { - return WorkFlowDefinitionResponseDTO - .builder().name( - TEST_WORKFLOW_NAME) - .works(Set.of(WorkDefinitionResponseDTO.builder().name(TEST_SUB_WORKFLOW_NAME) - .workType(WorkType.WORKFLOW).works(Set.of(WorkDefinitionResponseDTO.builder() - .name(TEST_TASK_NAME).workType(WorkType.TASK).build())) - .build())) - .build(); + LinkedHashSet workFlowWorks = new LinkedHashSet<>(); + LinkedHashSet taskWorks = new LinkedHashSet<>(); + + taskWorks.add(WorkDefinitionResponseDTO.builder().name(TEST_TASK_NAME).workType(WorkType.TASK).build()); + workFlowWorks.add(WorkDefinitionResponseDTO.builder().name(TEST_SUB_WORKFLOW_NAME).workType(WorkType.WORKFLOW) + .works(taskWorks).build()); + return WorkFlowDefinitionResponseDTO.builder().name(TEST_WORKFLOW_NAME).works(workFlowWorks).build(); } } diff --git a/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImplTest.java b/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImplTest.java index 18665dc6a..f1e5688e2 100644 --- a/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImplTest.java +++ b/workflow-service/src/test/java/com/redhat/parodos/workflow/definition/service/WorkFlowDefinitionServiceImplTest.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Optional; @@ -51,6 +52,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -313,9 +315,39 @@ public void getWorkFlowDefinitionWithoutData() { @Test public void getWorkFlowDefinitionsWithData() { // given - when(this.workFlowDefinitionRepository.findByTypeIsNot(WorkFlowType.CHECKER)).thenReturn( - Arrays.asList(sampleWorkFlowDefinition("workFLowOne"), sampleWorkFlowDefinition("workFLowTwo"))); + WorkFlowDefinition workFlowOne = sampleWorkFlowDefinition("workFLowOne"); + WorkFlowDefinition checker = sampleCheckerWorkFlowDefinition("checker"); + WorkParameter workParameter = WorkParameter.builder().key("key").description("the key").optional(false) + .type(WorkParameterType.URI).build(); + WorkFlowCheckerMappingDefinition workFlowCheckerMappingDefinition = WorkFlowCheckerMappingDefinition.builder() + .checkWorkFlow(checker).cronExpression("* * * * *") + .tasks(Collections.singletonList(sampleWorkFlowTaskDefinition(checker, "taskOfChecker", workParameter))) + .build(); + workFlowCheckerMappingDefinition.setId(UUID.randomUUID()); + WorkFlowTaskDefinition task01 = sampleWorkFlowTaskDefinitionWithChecker(workFlowOne, "task01", workParameter, + workFlowCheckerMappingDefinition); + WorkFlowTaskDefinition task02 = sampleWorkFlowTaskDefinition(workFlowOne, "task02", workParameter); + + WorkFlowWorkDefinition taskDefinition = WorkFlowWorkDefinition.builder().workFlowDefinition(workFlowOne) + .workDefinitionId(UUID.randomUUID()).workDefinitionType(WorkType.TASK).createDate(new Date()).build(); + taskDefinition.setId(UUID.randomUUID()); + WorkFlowWorkDefinition taskDefinition02 = WorkFlowWorkDefinition.builder().workFlowDefinition(workFlowOne) + .workDefinitionId(UUID.randomUUID()).workDefinitionType(WorkType.TASK).createDate(new Date()).build(); + taskDefinition02.setId(UUID.randomUUID()); + + workFlowOne.setNumberOfWorks(1); + + when(this.workFlowCheckerMappingDefinitionRepository.findById(workFlowCheckerMappingDefinition.getId())) + .thenReturn(Optional.of(workFlowCheckerMappingDefinition)); + when(this.workFlowTaskDefinitionRepository.findById(taskDefinition.getWorkDefinitionId())) + .thenReturn(Optional.of(task01)); + when(this.workFlowTaskDefinitionRepository.findById(taskDefinition02.getWorkDefinitionId())) + .thenReturn(Optional.of(task02)); + when(this.workFlowDefinitionRepository.findByTypeIsNot(WorkFlowType.CHECKER)) + .thenReturn(Arrays.asList(workFlowOne, sampleWorkFlowDefinition("workFLowTwo"))); + when(this.workFlowWorkRepository.findByWorkFlowDefinitionIdOrderByCreateDateAsc(workFlowOne.getId())) + .thenReturn(List.of(taskDefinition, taskDefinition02)); // when List workFlowDefinitionResponseDTOs = this.workFlowDefinitionService .getWorkFlowDefinitions(); @@ -323,8 +355,36 @@ public void getWorkFlowDefinitionsWithData() { // then assertNotNull(workFlowDefinitionResponseDTOs); assertEquals(workFlowDefinitionResponseDTOs.size(), 2); - assertEquals(workFlowDefinitionResponseDTOs.get(0).getName(), "workFLowOne"); - assertEquals(workFlowDefinitionResponseDTOs.get(0).getProperties().getVersion(), "1.0.0"); + + // check root WorkFlow + WorkFlowDefinitionResponseDTO workFlowOneResponseDTO = workFlowDefinitionResponseDTOs.get(0); + assertEquals(workFlowOneResponseDTO.getName(), "workFLowOne"); + assertEquals(workFlowOneResponseDTO.getType(), workFlowOne.getType()); + assertEquals(workFlowOneResponseDTO.getProcessingType(), workFlowOne.getProcessingType()); + assertNull(workFlowOneResponseDTO.getCronExpression()); + assertEquals(workFlowDefinitionResponseDTOs.get(1).getName(), "workFLowTwo"); + assertEquals(workFlowOneResponseDTO.getProperties().getVersion(), "1.0.0"); + assertFalse(workFlowOneResponseDTO.getWorks().isEmpty()); + + // check associated tasks + ArrayList tasks = new ArrayList<>(workFlowOneResponseDTO.getWorks()); + WorkDefinitionResponseDTO taskWorkUnit = tasks.get(0); + assertEquals(taskWorkUnit.getWorkFlowCheckerMappingDefinitionId(), workFlowCheckerMappingDefinition.getId()); + assertEquals(taskWorkUnit.getParameters().get(workParameter.getKey()), workParameter.getAsJsonSchema()); + assertEquals(taskWorkUnit.getName(), task01.getName()); + WorkDefinitionResponseDTO taskWorkUnit02 = tasks.get(1); + assertEquals(taskWorkUnit02.getName(), task02.getName()); + assertNull(taskWorkUnit02.getWorkFlowCheckerMappingDefinitionId()); + assertEquals(taskWorkUnit.getParameters().get(workParameter.getKey()), workParameter.getAsJsonSchema()); + + // check checker of task01 + WorkDefinitionResponseDTO checkerWorkUnit = taskWorkUnit.getWorks().stream().findFirst().get(); + assertEquals(checkerWorkUnit.getWorkType(), WorkType.CHECKER); + assertEquals(checkerWorkUnit.getName(), checker.getName()); + assertEquals(checkerWorkUnit.getProcessingType(), checker.getProcessingType()); + assertEquals(checkerWorkUnit.getCronExpression(), workFlowCheckerMappingDefinition.getCronExpression()); + assertEquals(checkerWorkUnit.getId(), checker.getId()); + verify(this.workFlowDefinitionRepository, times(1)).findByTypeIsNot(WorkFlowType.CHECKER); } @@ -453,13 +513,39 @@ private WorkFlowDefinition sampleWorkFlowDefinition(String name) { return workFlowDefinition; } + private WorkFlowDefinition sampleCheckerWorkFlowDefinition(String name) { + com.redhat.parodos.workflow.parameter.WorkParameter workParameter = com.redhat.parodos.workflow.parameter.WorkParameter + .builder().key(KEY).description(KEY_DESCRIPTION).optional(false) + .type(com.redhat.parodos.workflow.parameter.WorkParameterType.TEXT).build(); + + WorkFlowDefinition workFlowDefinition = WorkFlowDefinition.builder().name(name).type(WorkFlowType.CHECKER) + .properties(WorkFlowPropertiesDefinition.builder().version("1.0.0").build()) + .processingType(WorkFlowProcessingType.SEQUENTIAL) + .parameters(WorkFlowDTOUtil + .writeObjectValueAsString(Map.of(workParameter.getKey(), workParameter.getAsJsonSchema()))) + .numberOfWorks(1).build(); + workFlowDefinition.setId(UUID.randomUUID()); + return workFlowDefinition; + } + private WorkFlowTaskDefinition sampleWorkFlowTaskDefinition(WorkFlowDefinition workFlowDefinition, String workFlowTaskName, WorkParameter workParameter) { WorkFlowTaskDefinition workFlowTaskDefinition = WorkFlowTaskDefinition.builder() .workFlowDefinition(workFlowDefinition).name(workFlowTaskName) .parameters(WorkFlowDTOUtil .writeObjectValueAsString(Map.of(workParameter.getKey(), workParameter.getAsJsonSchema()))) - .build(); + .outputs("[]").build(); + workFlowTaskDefinition.setId(UUID.randomUUID()); + return workFlowTaskDefinition; + } + + private WorkFlowTaskDefinition sampleWorkFlowTaskDefinitionWithChecker(WorkFlowDefinition workFlowDefinition, + String workFlowTaskName, WorkParameter workParameter, WorkFlowCheckerMappingDefinition checker) { + WorkFlowTaskDefinition workFlowTaskDefinition = WorkFlowTaskDefinition.builder() + .workFlowDefinition(workFlowDefinition).name(workFlowTaskName) + .parameters(WorkFlowDTOUtil + .writeObjectValueAsString(Map.of(workParameter.getKey(), workParameter.getAsJsonSchema()))) + .workFlowCheckerMappingDefinition(checker).outputs("[]").build(); workFlowTaskDefinition.setId(UUID.randomUUID()); return workFlowTaskDefinition; }