From 630f68103d55e8aaf01c915c8468d75529ebddfd Mon Sep 17 00:00:00 2001 From: pratyush Date: Thu, 5 Mar 2026 19:54:24 +0000 Subject: [PATCH 1/3] Rename package structure and resources to `veloflow`, update workflow fetching logic, and enhance database configuration with connection timeouts --- .../dev/veloflow-service-configmap-dev.yaml | 2 +- pom.xml | 1 + .../SimpleWF.java => veloflow/VeloFlow.java} | 6 +- .../api/controller/InstanceController.java | 13 +- .../app/api/controller/TaskController.java | 10 +- .../advice/HostnameResponseBodyAdvice.java | 4 +- .../core/config/AppConfig.java | 10 +- .../core/context/RequestContext.java | 2 +- .../core/converter/JsonMapConverter.java | 12 +- .../converter/JsonPositionListConverter.java | 41 +++ .../core/data/dto/TaskExecutionResponse.java | 3 +- .../core/data/model/EventDefinition.java | 2 +- .../core/data/model/EventTypes.java | 2 +- .../core/data/model/GatewaySubTypes.java | 2 +- .../core/data/model/InstanceStatus.java | 2 +- .../core/data/model/Step.java | 4 +- .../core/data/model/StepTypes.java | 2 +- .../core/data/model/Task.java | 2 +- .../core/data/model/TaskStatus.java | 2 +- .../core/data/model/TaskSubTypes.java | 2 +- .../core/data/model/Transition.java | 26 +- .../core/data/model/Workflow.java | 20 +- .../core/data/model/WorkflowInstance.java | 4 +- .../core/data/repository/StepRepository.java | 4 +- .../core/data/repository/TaskRepository.java | 4 +- .../WorkflowInstanceRepository.java | 4 +- .../data/repository/WorkflowRepository.java | 11 +- .../core/executors/BaseTaskExecutor.java | 8 +- .../core/executors/DecisionTaskExecutor.java | 2 +- .../DefaultDecisionTaskExecutor.java | 16 +- .../executors/DefaultScriptTaskExecutor.java | 16 +- .../executors/DefaultSystemTaskExecutor.java | 16 +- .../executors/DefaultUserTaskExecutor.java | 16 +- .../core/executors/ExecutorRegistry.java | 22 +- .../core/executors/ScriptTaskExecutor.java | 2 +- .../core/executors/SystemTaskExecutor.java | 2 +- .../core/executors/UserTaskExecutor.java | 2 +- .../core/filter/RequestIdFilter.java | 4 +- .../core/filter/RequestLoggingFilter.java | 4 +- .../core/service/CommonTaskServices.java | 10 +- .../core/service/RunnerPools.java | 10 +- .../core/service/StepService.java | 14 +- .../core/service/TaskService.java | 6 +- .../core/service/WorkflowInstanceService.java | 6 +- .../core/service/WorkflowService.java | 16 +- .../api/controller/StepEditorController.java | 18 +- .../controller/WorkflowEditorController.java | 50 +-- .../editor/api/dto/AnchorDto.java | 5 +- .../editor/api/dto/PositionDto.java | 3 +- .../editor/api/dto/StepDto.java | 13 +- .../editor/api/dto/TaskDto.java | 2 +- .../editor/api/dto/TransitionDto.java | 10 +- .../editor/api/dto/WorkflowDto.java | 7 +- .../editor/api/dto/WorkflowInstanceDto.java | 4 +- .../editor/mapper/WorkflowMapper.java | 14 +- .../editor/model/Anchor.java | 8 +- .../editor/model/Position.java | 6 +- .../editor/model/enums/Side.java | 4 +- .../veloflow/editor/service/BpmnService.java | 309 ++++++++++++++++++ .../editor/service/StepEditorService.java | 48 +-- .../editor/service/WorkflowEditorService.java | 42 ++- .../exception/GlobalExceptionHandler.java | 22 +- src/main/resources/application.yml | 14 +- .../api/controller/StepCreationTest.java | 28 +- .../controller/WorkflowControllerTest.java | 14 +- .../editor/service/BpmnServiceTest.java | 83 +++++ 66 files changed, 795 insertions(+), 278 deletions(-) rename src/main/java/xyz/pkay/{simpleWf/SimpleWF.java => veloflow/VeloFlow.java} (91%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/app/api/controller/InstanceController.java (78%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/app/api/controller/TaskController.java (78%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/advice/HostnameResponseBodyAdvice.java (96%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/config/AppConfig.java (87%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/context/RequestContext.java (89%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/converter/JsonMapConverter.java (92%) create mode 100644 src/main/java/xyz/pkay/veloflow/core/converter/JsonPositionListConverter.java rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/dto/TaskExecutionResponse.java (80%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/EventDefinition.java (70%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/EventTypes.java (65%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/GatewaySubTypes.java (74%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/InstanceStatus.java (61%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/Step.java (92%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/StepTypes.java (58%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/Task.java (96%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/TaskStatus.java (68%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/TaskSubTypes.java (78%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/Transition.java (74%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/Workflow.java (82%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/model/WorkflowInstance.java (93%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/repository/StepRepository.java (69%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/repository/TaskRepository.java (80%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/repository/WorkflowInstanceRepository.java (67%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/data/repository/WorkflowRepository.java (52%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/BaseTaskExecutor.java (61%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/DecisionTaskExecutor.java (61%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/DefaultDecisionTaskExecutor.java (72%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/DefaultScriptTaskExecutor.java (72%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/DefaultSystemTaskExecutor.java (72%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/DefaultUserTaskExecutor.java (73%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/ExecutorRegistry.java (94%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/ScriptTaskExecutor.java (61%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/SystemTaskExecutor.java (61%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/executors/UserTaskExecutor.java (60%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/filter/RequestIdFilter.java (93%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/filter/RequestLoggingFilter.java (93%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/service/CommonTaskServices.java (77%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/service/RunnerPools.java (96%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/service/StepService.java (69%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/service/TaskService.java (85%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/service/WorkflowInstanceService.java (93%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/core/service/WorkflowService.java (76%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/controller/StepEditorController.java (88%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/controller/WorkflowEditorController.java (53%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/dto/AnchorDto.java (71%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/dto/PositionDto.java (83%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/dto/StepDto.java (80%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/dto/TaskDto.java (92%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/dto/TransitionDto.java (86%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/dto/WorkflowDto.java (87%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/api/dto/WorkflowInstanceDto.java (84%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/mapper/WorkflowMapper.java (95%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/model/Anchor.java (83%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/model/Position.java (85%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/model/enums/Side.java (85%) create mode 100644 src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/service/StepEditorService.java (65%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/editor/service/WorkflowEditorService.java (55%) rename src/main/java/xyz/pkay/{simpleWf => veloflow}/exception/GlobalExceptionHandler.java (95%) rename src/test/java/xyz/pkay/{simpleWf => veloflow}/api/controller/StepCreationTest.java (70%) rename src/test/java/xyz/pkay/{simpleWf => veloflow}/api/controller/WorkflowControllerTest.java (82%) create mode 100644 src/test/java/xyz/pkay/veloflow/editor/service/BpmnServiceTest.java diff --git a/configmap/dev/veloflow-service-configmap-dev.yaml b/configmap/dev/veloflow-service-configmap-dev.yaml index bba7f4e..18b6de9 100644 --- a/configmap/dev/veloflow-service-configmap-dev.yaml +++ b/configmap/dev/veloflow-service-configmap-dev.yaml @@ -4,6 +4,6 @@ metadata: name: veloflow-service-configmap-dev data: APP_ENV: dev - DB_URL: jdbc:mariadb://192.168.1.206:3306/c10_wrk_flw_v1 + DB_URL: jdbc:mariadb://192.168.1.206:3306/c10_wrk_flw_v1?tcpKeepAlive=true&connectTimeout=5000&socketTimeout=10000 DB_USER: c10_wrk_flw SHOW_SQL: "true" \ No newline at end of file diff --git a/pom.xml b/pom.xml index 947d4a4..4645e4c 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,7 @@ org.mariadb.jdbc mariadb-java-client + 3.5.7 runtime diff --git a/src/main/java/xyz/pkay/simpleWf/SimpleWF.java b/src/main/java/xyz/pkay/veloflow/VeloFlow.java similarity index 91% rename from src/main/java/xyz/pkay/simpleWf/SimpleWF.java rename to src/main/java/xyz/pkay/veloflow/VeloFlow.java index fd2dec4..4b7ba40 100644 --- a/src/main/java/xyz/pkay/simpleWf/SimpleWF.java +++ b/src/main/java/xyz/pkay/veloflow/VeloFlow.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf; +package xyz.pkay.veloflow; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -12,10 +12,10 @@ import java.util.Map; @SpringBootApplication @RestController -public class SimpleWF { +public class VeloFlow { public static void main(String[] args) { - SpringApplication.run(SimpleWF.class, args); + SpringApplication.run(VeloFlow.class, args); } @GetMapping("/") diff --git a/src/main/java/xyz/pkay/simpleWf/app/api/controller/InstanceController.java b/src/main/java/xyz/pkay/veloflow/app/api/controller/InstanceController.java similarity index 78% rename from src/main/java/xyz/pkay/simpleWf/app/api/controller/InstanceController.java rename to src/main/java/xyz/pkay/veloflow/app/api/controller/InstanceController.java index e70db8e..e2cc6d0 100644 --- a/src/main/java/xyz/pkay/simpleWf/app/api/controller/InstanceController.java +++ b/src/main/java/xyz/pkay/veloflow/app/api/controller/InstanceController.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.app.api.controller; +package xyz.pkay.veloflow.app.api.controller; import io.swagger.v3.oas.annotations.tags.Tag; @@ -8,9 +8,9 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import xyz.pkay.simpleWf.core.service.WorkflowInstanceService; -import xyz.pkay.simpleWf.editor.api.dto.WorkflowInstanceDto; -import xyz.pkay.simpleWf.editor.mapper.WorkflowMapper; +import xyz.pkay.veloflow.core.service.WorkflowInstanceService; +import xyz.pkay.veloflow.editor.api.dto.WorkflowInstanceDto; +import xyz.pkay.veloflow.editor.mapper.WorkflowMapper; import java.util.UUID; @@ -20,10 +20,11 @@ import java.util.UUID; @Tags({@Tag(name = "Workflow Instance"), @Tag(name = "Executor")}) public class InstanceController { - + private final WorkflowMapper mapper; + private final WorkflowInstanceService workflowInstanceService; - + @PostMapping("/start/{workflowId}") public WorkflowInstanceDto startProcess(@PathVariable UUID workflowId) { return mapper.toDto(workflowInstanceService.createInstance(workflowId)); diff --git a/src/main/java/xyz/pkay/simpleWf/app/api/controller/TaskController.java b/src/main/java/xyz/pkay/veloflow/app/api/controller/TaskController.java similarity index 78% rename from src/main/java/xyz/pkay/simpleWf/app/api/controller/TaskController.java rename to src/main/java/xyz/pkay/veloflow/app/api/controller/TaskController.java index a3f236a..402fdd6 100644 --- a/src/main/java/xyz/pkay/simpleWf/app/api/controller/TaskController.java +++ b/src/main/java/xyz/pkay/veloflow/app/api/controller/TaskController.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.app.api.controller; +package xyz.pkay.veloflow.app.api.controller; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; @@ -6,10 +6,10 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import xyz.pkay.simpleWf.core.service.RunnerPools; -import xyz.pkay.simpleWf.core.service.TaskService; -import xyz.pkay.simpleWf.editor.api.dto.TaskDto; -import xyz.pkay.simpleWf.editor.mapper.WorkflowMapper; +import xyz.pkay.veloflow.core.service.RunnerPools; +import xyz.pkay.veloflow.core.service.TaskService; +import xyz.pkay.veloflow.editor.api.dto.TaskDto; +import xyz.pkay.veloflow.editor.mapper.WorkflowMapper; import java.util.List; import java.util.Map; diff --git a/src/main/java/xyz/pkay/simpleWf/core/advice/HostnameResponseBodyAdvice.java b/src/main/java/xyz/pkay/veloflow/core/advice/HostnameResponseBodyAdvice.java similarity index 96% rename from src/main/java/xyz/pkay/simpleWf/core/advice/HostnameResponseBodyAdvice.java rename to src/main/java/xyz/pkay/veloflow/core/advice/HostnameResponseBodyAdvice.java index da34734..b175bae 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/advice/HostnameResponseBodyAdvice.java +++ b/src/main/java/xyz/pkay/veloflow/core/advice/HostnameResponseBodyAdvice.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.advice; +package xyz.pkay.veloflow.core.advice; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; @@ -7,7 +7,7 @@ import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; -import xyz.pkay.simpleWf.core.context.RequestContext; +import xyz.pkay.veloflow.core.context.RequestContext; import java.net.InetAddress; import java.net.UnknownHostException; diff --git a/src/main/java/xyz/pkay/simpleWf/core/config/AppConfig.java b/src/main/java/xyz/pkay/veloflow/core/config/AppConfig.java similarity index 87% rename from src/main/java/xyz/pkay/simpleWf/core/config/AppConfig.java rename to src/main/java/xyz/pkay/veloflow/core/config/AppConfig.java index 5363bb8..0d09a9c 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/config/AppConfig.java +++ b/src/main/java/xyz/pkay/veloflow/core/config/AppConfig.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.config; +package xyz.pkay.veloflow.core.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -9,14 +9,18 @@ import org.springframework.context.annotation.Configuration; @Data public class AppConfig { String env; + ThreadPoolConfig processThreadPool = new ThreadPoolConfig(); + ThreadPoolConfig taskThreadPool = new ThreadPoolConfig(); - + @Data public static class ThreadPoolConfig { int corePoolSize = 1; + int keepAliveSeconds = 1800; + int maxPoolSize = 2; } - + } diff --git a/src/main/java/xyz/pkay/simpleWf/core/context/RequestContext.java b/src/main/java/xyz/pkay/veloflow/core/context/RequestContext.java similarity index 89% rename from src/main/java/xyz/pkay/simpleWf/core/context/RequestContext.java rename to src/main/java/xyz/pkay/veloflow/core/context/RequestContext.java index d9bd649..d702644 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/context/RequestContext.java +++ b/src/main/java/xyz/pkay/veloflow/core/context/RequestContext.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.context; +package xyz.pkay.veloflow.core.context; public class RequestContext { private static final ThreadLocal requestId = new ThreadLocal<>(); diff --git a/src/main/java/xyz/pkay/simpleWf/core/converter/JsonMapConverter.java b/src/main/java/xyz/pkay/veloflow/core/converter/JsonMapConverter.java similarity index 92% rename from src/main/java/xyz/pkay/simpleWf/core/converter/JsonMapConverter.java rename to src/main/java/xyz/pkay/veloflow/core/converter/JsonMapConverter.java index 48126ac..1414440 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/converter/JsonMapConverter.java +++ b/src/main/java/xyz/pkay/veloflow/core/converter/JsonMapConverter.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.converter; +package xyz.pkay.veloflow.core.converter; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; @@ -6,16 +6,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.persistence.AttributeConverter; import jakarta.persistence.Converter; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.data.model.WorkflowInstance; +import xyz.pkay.veloflow.core.data.model.WorkflowInstance; import java.util.HashMap; @Converter @Component public class JsonMapConverter implements AttributeConverter { - + private static final ObjectMapper objectMapper = new ObjectMapper(); - + @Override public String convertToDatabaseColumn(WorkflowInstance.RuntimeData attribute) { try { @@ -29,7 +29,7 @@ public class JsonMapConverter implements AttributeConverter, String> { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public String convertToDatabaseColumn(List attribute) { + try { + if (attribute == null) { + attribute = new ArrayList<>(); + } + return objectMapper.writeValueAsString(attribute); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + @Override + public List convertToEntityAttribute(String dbData) { + try { + return dbData == null || dbData.isEmpty() ? new ArrayList<>() : objectMapper.readValue(dbData, new TypeReference>() { + }); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/dto/TaskExecutionResponse.java b/src/main/java/xyz/pkay/veloflow/core/data/dto/TaskExecutionResponse.java similarity index 80% rename from src/main/java/xyz/pkay/simpleWf/core/data/dto/TaskExecutionResponse.java rename to src/main/java/xyz/pkay/veloflow/core/data/dto/TaskExecutionResponse.java index d2b9e44..0560cda 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/dto/TaskExecutionResponse.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/dto/TaskExecutionResponse.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.dto; +package xyz.pkay.veloflow.core.data.dto; import lombok.Data; @@ -8,5 +8,6 @@ import java.util.Map; @Data public class TaskExecutionResponse { private List actions; + private Map outputData; } diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/EventDefinition.java b/src/main/java/xyz/pkay/veloflow/core/data/model/EventDefinition.java similarity index 70% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/EventDefinition.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/EventDefinition.java index 3453f8c..da8f47b 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/EventDefinition.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/EventDefinition.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; public enum EventDefinition { NONE, diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/EventTypes.java b/src/main/java/xyz/pkay/veloflow/core/data/model/EventTypes.java similarity index 65% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/EventTypes.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/EventTypes.java index f6233c4..37d99b9 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/EventTypes.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/EventTypes.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; public enum EventTypes { START_EVENT, diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/GatewaySubTypes.java b/src/main/java/xyz/pkay/veloflow/core/data/model/GatewaySubTypes.java similarity index 74% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/GatewaySubTypes.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/GatewaySubTypes.java index d95e1a4..c376259 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/GatewaySubTypes.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/GatewaySubTypes.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; public enum GatewaySubTypes { EXCLUSIVE_GATEWAY, diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/InstanceStatus.java b/src/main/java/xyz/pkay/veloflow/core/data/model/InstanceStatus.java similarity index 61% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/InstanceStatus.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/InstanceStatus.java index 0a3bda8..cbccf2a 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/InstanceStatus.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/InstanceStatus.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; public enum InstanceStatus { RUNNING, diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/Step.java b/src/main/java/xyz/pkay/veloflow/core/data/model/Step.java similarity index 92% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/Step.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/Step.java index e716363..2ad9b33 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/Step.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/Step.java @@ -1,9 +1,9 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; -import xyz.pkay.simpleWf.editor.model.Position; +import xyz.pkay.veloflow.editor.model.Position; import java.util.UUID; diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/StepTypes.java b/src/main/java/xyz/pkay/veloflow/core/data/model/StepTypes.java similarity index 58% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/StepTypes.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/StepTypes.java index 146bfe4..f0ccf77 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/StepTypes.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/StepTypes.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; public enum StepTypes { TASK, diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/Task.java b/src/main/java/xyz/pkay/veloflow/core/data/model/Task.java similarity index 96% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/Task.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/Task.java index 56a2333..a0abf13 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/Task.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/Task.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; import jakarta.persistence.*; import lombok.Getter; diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/TaskStatus.java b/src/main/java/xyz/pkay/veloflow/core/data/model/TaskStatus.java similarity index 68% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/TaskStatus.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/TaskStatus.java index 67aeb15..8ae4b80 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/TaskStatus.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/TaskStatus.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; public enum TaskStatus { NEW, ASSIGNED, PRE_EXECUTE, POST_EXECUTE, COMPLETED, FAILED diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/TaskSubTypes.java b/src/main/java/xyz/pkay/veloflow/core/data/model/TaskSubTypes.java similarity index 78% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/TaskSubTypes.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/TaskSubTypes.java index b839d5f..3b06cc9 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/TaskSubTypes.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/TaskSubTypes.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; public enum TaskSubTypes { USER_TASK, diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/Transition.java b/src/main/java/xyz/pkay/veloflow/core/data/model/Transition.java similarity index 74% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/Transition.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/Transition.java index 7fbd745..c7130fa 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/Transition.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/Transition.java @@ -1,11 +1,14 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; -import xyz.pkay.simpleWf.editor.model.Anchor; -import xyz.pkay.simpleWf.editor.model.Position; +import xyz.pkay.veloflow.core.converter.JsonPositionListConverter; +import xyz.pkay.veloflow.editor.model.Anchor; +import xyz.pkay.veloflow.editor.model.Position; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; @Entity @@ -13,37 +16,46 @@ import java.util.UUID; @Getter @Setter public class Transition { - + @Column(nullable = false) private String actionName; + @Column(nullable = false) private String actionValue; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "current_step_id", nullable = false) private Step currentStep; + @Embedded @AttributeOverrides({ @AttributeOverride(name = "side", column = @Column(name = "from_anchor_side")), @AttributeOverride(name = "sideIndex", column = @Column(name = "from_anchor_index")) }) private Anchor fromAnchor; + @Id @GeneratedValue(strategy = GenerationType.UUID) private UUID id; + @Column private String name; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "next_step_id", nullable = false) private Step nextStep; + @Embedded @AttributeOverrides({ @AttributeOverride(name = "side", column = @Column(name = "to_anchor_side")), @AttributeOverride(name = "sideIndex", column = @Column(name = "to_anchor_index")) }) private Anchor toAnchor; - @ElementCollection - @CollectionTable(name = "transition_waypoints", joinColumns = @JoinColumn(name = "transition_id")) - private java.util.List waypoints = new java.util.ArrayList<>(); + + @Convert(converter = JsonPositionListConverter.class) + @Column(columnDefinition = "TEXT") + private List waypoints = new ArrayList<>(); + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "workflow_id", nullable = false) private Workflow workflow; diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/Workflow.java b/src/main/java/xyz/pkay/veloflow/core/data/model/Workflow.java similarity index 82% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/Workflow.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/Workflow.java index b167be2..d324600 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/Workflow.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/Workflow.java @@ -1,46 +1,50 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import java.util.*; @Entity @Table(name = "workflows") public class Workflow { - + @Getter private LocalDateTime createdAt; + // Getters and Setters @Getter @Setter @Id @GeneratedValue(strategy = GenerationType.UUID) private UUID id; + @Getter @OneToMany(mappedBy = "workflow", cascade = CascadeType.ALL, orphanRemoval = true) private List instances = new ArrayList<>(); + @Getter @Setter @Column(nullable = false) private String name; + @Setter @Getter @Column(nullable = false) private String status; // e.g., PENDING, RUNNING, COMPLETED + @Getter @Setter @OneToMany(mappedBy = "workflow", cascade = CascadeType.ALL, orphanRemoval = true) - private List steps = new ArrayList<>(); + private Set steps = new HashSet<>(); + @Getter @Setter @OneToMany(mappedBy = "workflow", cascade = CascadeType.ALL, orphanRemoval = true) - private List transitions = new ArrayList<>(); - + private Set transitions = new HashSet<>(); + @PrePersist protected void onCreate() { createdAt = LocalDateTime.now(); diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/model/WorkflowInstance.java b/src/main/java/xyz/pkay/veloflow/core/data/model/WorkflowInstance.java similarity index 93% rename from src/main/java/xyz/pkay/simpleWf/core/data/model/WorkflowInstance.java rename to src/main/java/xyz/pkay/veloflow/core/data/model/WorkflowInstance.java index 59b0e60..9b85734 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/model/WorkflowInstance.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/WorkflowInstance.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.core.data.model; +package xyz.pkay.veloflow.core.data.model; import jakarta.persistence.*; import lombok.Data; import lombok.Getter; import lombok.Setter; -import xyz.pkay.simpleWf.core.converter.JsonMapConverter; +import xyz.pkay.veloflow.core.converter.JsonMapConverter; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/repository/StepRepository.java b/src/main/java/xyz/pkay/veloflow/core/data/repository/StepRepository.java similarity index 69% rename from src/main/java/xyz/pkay/simpleWf/core/data/repository/StepRepository.java rename to src/main/java/xyz/pkay/veloflow/core/data/repository/StepRepository.java index f590164..5456d32 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/repository/StepRepository.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/repository/StepRepository.java @@ -1,8 +1,8 @@ -package xyz.pkay.simpleWf.core.data.repository; +package xyz.pkay.veloflow.core.data.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import xyz.pkay.simpleWf.core.data.model.Step; +import xyz.pkay.veloflow.core.data.model.Step; import java.util.UUID; diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/repository/TaskRepository.java b/src/main/java/xyz/pkay/veloflow/core/data/repository/TaskRepository.java similarity index 80% rename from src/main/java/xyz/pkay/simpleWf/core/data/repository/TaskRepository.java rename to src/main/java/xyz/pkay/veloflow/core/data/repository/TaskRepository.java index 5039ceb..d8736e7 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/repository/TaskRepository.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/repository/TaskRepository.java @@ -1,9 +1,9 @@ -package xyz.pkay.simpleWf.core.data.repository; +package xyz.pkay.veloflow.core.data.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -import xyz.pkay.simpleWf.core.data.model.Task; +import xyz.pkay.veloflow.core.data.model.Task; import java.util.List; diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/repository/WorkflowInstanceRepository.java b/src/main/java/xyz/pkay/veloflow/core/data/repository/WorkflowInstanceRepository.java similarity index 67% rename from src/main/java/xyz/pkay/simpleWf/core/data/repository/WorkflowInstanceRepository.java rename to src/main/java/xyz/pkay/veloflow/core/data/repository/WorkflowInstanceRepository.java index 92bac17..63d87d4 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/repository/WorkflowInstanceRepository.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/repository/WorkflowInstanceRepository.java @@ -1,8 +1,8 @@ -package xyz.pkay.simpleWf.core.data.repository; +package xyz.pkay.veloflow.core.data.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import xyz.pkay.simpleWf.core.data.model.WorkflowInstance; +import xyz.pkay.veloflow.core.data.model.WorkflowInstance; @Repository public interface WorkflowInstanceRepository extends JpaRepository { diff --git a/src/main/java/xyz/pkay/simpleWf/core/data/repository/WorkflowRepository.java b/src/main/java/xyz/pkay/veloflow/core/data/repository/WorkflowRepository.java similarity index 52% rename from src/main/java/xyz/pkay/simpleWf/core/data/repository/WorkflowRepository.java rename to src/main/java/xyz/pkay/veloflow/core/data/repository/WorkflowRepository.java index 8707a28..1a72072 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/data/repository/WorkflowRepository.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/repository/WorkflowRepository.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.core.data.repository; +package xyz.pkay.veloflow.core.data.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import xyz.pkay.simpleWf.core.data.model.Workflow; +import xyz.pkay.veloflow.core.data.model.Workflow; import java.util.Optional; import java.util.UUID; @@ -12,6 +12,9 @@ import java.util.UUID; @Repository public interface WorkflowRepository extends JpaRepository { - @Query("SELECT w FROM Workflow w LEFT JOIN FETCH w.steps WHERE w.id = :id") - Optional findByIdWithSteps(@Param("id") UUID id); + @Query("SELECT w FROM Workflow w " + + "LEFT JOIN FETCH w.steps " + + "LEFT JOIN FETCH w.transitions " + + "WHERE w.id = :id") + Optional findByIdWithFullDetails(@Param("id") UUID id); } \ No newline at end of file diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/BaseTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/BaseTaskExecutor.java similarity index 61% rename from src/main/java/xyz/pkay/simpleWf/core/executors/BaseTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/BaseTaskExecutor.java index 5a7ab45..ebcae4e 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/BaseTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/BaseTaskExecutor.java @@ -1,9 +1,9 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; -import xyz.pkay.simpleWf.core.data.dto.TaskExecutionResponse; -import xyz.pkay.simpleWf.core.data.model.Task; -import xyz.pkay.simpleWf.core.data.model.TaskStatus; +import xyz.pkay.veloflow.core.data.dto.TaskExecutionResponse; +import xyz.pkay.veloflow.core.data.model.Task; +import xyz.pkay.veloflow.core.data.model.TaskStatus; import java.util.UUID; diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/DecisionTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/DecisionTaskExecutor.java similarity index 61% rename from src/main/java/xyz/pkay/simpleWf/core/executors/DecisionTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/DecisionTaskExecutor.java index 0cda865..472d6ff 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/DecisionTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/DecisionTaskExecutor.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; public interface DecisionTaskExecutor extends BaseTaskExecutor { } diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/DefaultDecisionTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/DefaultDecisionTaskExecutor.java similarity index 72% rename from src/main/java/xyz/pkay/simpleWf/core/executors/DefaultDecisionTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/DefaultDecisionTaskExecutor.java index 786d22a..1474057 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/DefaultDecisionTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/DefaultDecisionTaskExecutor.java @@ -1,8 +1,8 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.data.dto.TaskExecutionResponse; -import xyz.pkay.simpleWf.core.data.model.Task; +import xyz.pkay.veloflow.core.data.dto.TaskExecutionResponse; +import xyz.pkay.veloflow.core.data.model.Task; import java.util.UUID; @@ -12,19 +12,19 @@ public class DefaultDecisionTaskExecutor implements DecisionTaskExecutor { public TaskExecutionResponse execute(Task task) { return null; } - + @Override public Task init(Long pid, UUID stepId) { return null; } - + @Override public void interrupt() { - + } - + @Override public void preExecute(Long taskId) { - + } } diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/DefaultScriptTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/DefaultScriptTaskExecutor.java similarity index 72% rename from src/main/java/xyz/pkay/simpleWf/core/executors/DefaultScriptTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/DefaultScriptTaskExecutor.java index 6d5521c..5bc30f9 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/DefaultScriptTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/DefaultScriptTaskExecutor.java @@ -1,8 +1,8 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.data.dto.TaskExecutionResponse; -import xyz.pkay.simpleWf.core.data.model.Task; +import xyz.pkay.veloflow.core.data.dto.TaskExecutionResponse; +import xyz.pkay.veloflow.core.data.model.Task; import java.util.UUID; @@ -12,19 +12,19 @@ public class DefaultScriptTaskExecutor implements ScriptTaskExecutor { public TaskExecutionResponse execute(Task task) { return null; } - + @Override public Task init(Long pid, UUID stepId) { return null; } - + @Override public void interrupt() { - + } - + @Override public void preExecute(Long taskId) { - + } } diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/DefaultSystemTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/DefaultSystemTaskExecutor.java similarity index 72% rename from src/main/java/xyz/pkay/simpleWf/core/executors/DefaultSystemTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/DefaultSystemTaskExecutor.java index cb7fd94..df96f69 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/DefaultSystemTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/DefaultSystemTaskExecutor.java @@ -1,8 +1,8 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.data.dto.TaskExecutionResponse; -import xyz.pkay.simpleWf.core.data.model.Task; +import xyz.pkay.veloflow.core.data.dto.TaskExecutionResponse; +import xyz.pkay.veloflow.core.data.model.Task; import java.util.UUID; @@ -12,19 +12,19 @@ public class DefaultSystemTaskExecutor implements SystemTaskExecutor { public TaskExecutionResponse execute(Task task) { return null; } - + @Override public Task init(Long pid, UUID stepId) { return null; } - + @Override public void interrupt() { - + } - + @Override public void preExecute(Long taskId) { - + } } diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/DefaultUserTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/DefaultUserTaskExecutor.java similarity index 73% rename from src/main/java/xyz/pkay/simpleWf/core/executors/DefaultUserTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/DefaultUserTaskExecutor.java index d7602ac..9ece40c 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/DefaultUserTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/DefaultUserTaskExecutor.java @@ -1,14 +1,14 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.data.dto.TaskExecutionResponse; -import xyz.pkay.simpleWf.core.data.model.Task; -import xyz.pkay.simpleWf.core.data.model.WorkflowInstance; -import xyz.pkay.simpleWf.core.data.repository.WorkflowInstanceRepository; -import xyz.pkay.simpleWf.core.service.CommonTaskServices; -import xyz.pkay.simpleWf.core.service.StepService; -import xyz.pkay.simpleWf.core.service.TaskService; +import xyz.pkay.veloflow.core.data.dto.TaskExecutionResponse; +import xyz.pkay.veloflow.core.data.model.Task; +import xyz.pkay.veloflow.core.data.model.WorkflowInstance; +import xyz.pkay.veloflow.core.data.repository.WorkflowInstanceRepository; +import xyz.pkay.veloflow.core.service.CommonTaskServices; +import xyz.pkay.veloflow.core.service.StepService; +import xyz.pkay.veloflow.core.service.TaskService; import java.util.UUID; diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/ExecutorRegistry.java b/src/main/java/xyz/pkay/veloflow/core/executors/ExecutorRegistry.java similarity index 94% rename from src/main/java/xyz/pkay/simpleWf/core/executors/ExecutorRegistry.java rename to src/main/java/xyz/pkay/veloflow/core/executors/ExecutorRegistry.java index 7b3a51b..0888632 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/ExecutorRegistry.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/ExecutorRegistry.java @@ -1,9 +1,9 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.data.model.Step; -import xyz.pkay.simpleWf.core.data.model.StepTypes; +import xyz.pkay.veloflow.core.data.model.Step; +import xyz.pkay.veloflow.core.data.model.StepTypes; import java.beans.Introspector; import java.util.Map; @@ -11,19 +11,19 @@ import java.util.Map; @Component @Slf4j public class ExecutorRegistry { - + private final Map executorsByBeanName; - + public ExecutorRegistry(Map executorsByBeanName) { // Make it unmodifiable to guarantee no accidental mutation in the hot path this.executorsByBeanName = Map.copyOf(executorsByBeanName); log.info("ExecutorRegistry initialized with {} executors", this.executorsByBeanName.size()); } - + private static String beanName(Class clazz) { return Introspector.decapitalize(clazz.getSimpleName()); } - + private BaseTaskExecutor required(String beanName, Step step) { BaseTaskExecutor ex = executorsByBeanName.get(beanName); if (ex == null) { @@ -33,16 +33,16 @@ public class ExecutorRegistry { } return ex; } - + public BaseTaskExecutor resolve(Step step) { if (step == null) throw new IllegalArgumentException("step must not be null"); - + String name = step.getExecutorClassName(); if (name != null && !name.isBlank()) { BaseTaskExecutor exact = executorsByBeanName.get(name); if (exact != null) return exact; } - + // fallback (no caching of misses) if (step.getType() == StepTypes.TASK && step.getTaskSubType() != null) { switch (step.getTaskSubType()) { @@ -74,7 +74,7 @@ public class ExecutorRegistry { // Events might not have executors or might have default ones throw new IllegalArgumentException("Events do not have default executors yet"); } - + throw new IllegalArgumentException("Unsupported step type or missing sub-type: " + step.getType()); } } \ No newline at end of file diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/ScriptTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/ScriptTaskExecutor.java similarity index 61% rename from src/main/java/xyz/pkay/simpleWf/core/executors/ScriptTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/ScriptTaskExecutor.java index 70cc917..bba4402 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/ScriptTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/ScriptTaskExecutor.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; public interface ScriptTaskExecutor extends BaseTaskExecutor { } diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/SystemTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/SystemTaskExecutor.java similarity index 61% rename from src/main/java/xyz/pkay/simpleWf/core/executors/SystemTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/SystemTaskExecutor.java index a62540a..0da2da5 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/SystemTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/SystemTaskExecutor.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; public interface SystemTaskExecutor extends BaseTaskExecutor { } diff --git a/src/main/java/xyz/pkay/simpleWf/core/executors/UserTaskExecutor.java b/src/main/java/xyz/pkay/veloflow/core/executors/UserTaskExecutor.java similarity index 60% rename from src/main/java/xyz/pkay/simpleWf/core/executors/UserTaskExecutor.java rename to src/main/java/xyz/pkay/veloflow/core/executors/UserTaskExecutor.java index eebfba6..7fb826b 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/executors/UserTaskExecutor.java +++ b/src/main/java/xyz/pkay/veloflow/core/executors/UserTaskExecutor.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.executors; +package xyz.pkay.veloflow.core.executors; public interface UserTaskExecutor extends BaseTaskExecutor { } diff --git a/src/main/java/xyz/pkay/simpleWf/core/filter/RequestIdFilter.java b/src/main/java/xyz/pkay/veloflow/core/filter/RequestIdFilter.java similarity index 93% rename from src/main/java/xyz/pkay/simpleWf/core/filter/RequestIdFilter.java rename to src/main/java/xyz/pkay/veloflow/core/filter/RequestIdFilter.java index 6caa181..259250a 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/filter/RequestIdFilter.java +++ b/src/main/java/xyz/pkay/veloflow/core/filter/RequestIdFilter.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.core.filter; +package xyz.pkay.veloflow.core.filter; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; @@ -6,7 +6,7 @@ import org.slf4j.MDC; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.context.RequestContext; +import xyz.pkay.veloflow.core.context.RequestContext; import java.io.IOException; import java.util.UUID; diff --git a/src/main/java/xyz/pkay/simpleWf/core/filter/RequestLoggingFilter.java b/src/main/java/xyz/pkay/veloflow/core/filter/RequestLoggingFilter.java similarity index 93% rename from src/main/java/xyz/pkay/simpleWf/core/filter/RequestLoggingFilter.java rename to src/main/java/xyz/pkay/veloflow/core/filter/RequestLoggingFilter.java index 8769013..27991ca 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/filter/RequestLoggingFilter.java +++ b/src/main/java/xyz/pkay/veloflow/core/filter/RequestLoggingFilter.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.core.filter; +package xyz.pkay.veloflow.core.filter; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.context.RequestContext; +import xyz.pkay.veloflow.core.context.RequestContext; import java.io.IOException; import java.net.InetAddress; diff --git a/src/main/java/xyz/pkay/simpleWf/core/service/CommonTaskServices.java b/src/main/java/xyz/pkay/veloflow/core/service/CommonTaskServices.java similarity index 77% rename from src/main/java/xyz/pkay/simpleWf/core/service/CommonTaskServices.java rename to src/main/java/xyz/pkay/veloflow/core/service/CommonTaskServices.java index cbc70f8..baec1a7 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/service/CommonTaskServices.java +++ b/src/main/java/xyz/pkay/veloflow/core/service/CommonTaskServices.java @@ -1,12 +1,12 @@ -package xyz.pkay.simpleWf.core.service; +package xyz.pkay.veloflow.core.service; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.data.model.Step; -import xyz.pkay.simpleWf.core.data.model.Task; -import xyz.pkay.simpleWf.core.data.model.TaskStatus; -import xyz.pkay.simpleWf.core.data.model.WorkflowInstance; +import xyz.pkay.veloflow.core.data.model.Step; +import xyz.pkay.veloflow.core.data.model.Task; +import xyz.pkay.veloflow.core.data.model.TaskStatus; +import xyz.pkay.veloflow.core.data.model.WorkflowInstance; import java.util.UUID; diff --git a/src/main/java/xyz/pkay/simpleWf/core/service/RunnerPools.java b/src/main/java/xyz/pkay/veloflow/core/service/RunnerPools.java similarity index 96% rename from src/main/java/xyz/pkay/simpleWf/core/service/RunnerPools.java rename to src/main/java/xyz/pkay/veloflow/core/service/RunnerPools.java index eb58426..e838737 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/service/RunnerPools.java +++ b/src/main/java/xyz/pkay/veloflow/core/service/RunnerPools.java @@ -1,11 +1,11 @@ -package xyz.pkay.simpleWf.core.service; +package xyz.pkay.veloflow.core.service; import jakarta.annotation.PreDestroy; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.config.AppConfig; -import xyz.pkay.simpleWf.core.data.model.Task; -import xyz.pkay.simpleWf.core.executors.BaseTaskExecutor; -import xyz.pkay.simpleWf.core.executors.ExecutorRegistry; +import xyz.pkay.veloflow.core.config.AppConfig; +import xyz.pkay.veloflow.core.data.model.Task; +import xyz.pkay.veloflow.core.executors.BaseTaskExecutor; +import xyz.pkay.veloflow.core.executors.ExecutorRegistry; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/xyz/pkay/simpleWf/core/service/StepService.java b/src/main/java/xyz/pkay/veloflow/core/service/StepService.java similarity index 69% rename from src/main/java/xyz/pkay/simpleWf/core/service/StepService.java rename to src/main/java/xyz/pkay/veloflow/core/service/StepService.java index a8c6e4f..523afb3 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/service/StepService.java +++ b/src/main/java/xyz/pkay/veloflow/core/service/StepService.java @@ -1,19 +1,19 @@ -package xyz.pkay.simpleWf.core.service; +package xyz.pkay.veloflow.core.service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import xyz.pkay.simpleWf.core.data.model.Step; -import xyz.pkay.simpleWf.core.data.repository.StepRepository; +import xyz.pkay.veloflow.core.data.model.Step; +import xyz.pkay.veloflow.core.data.repository.StepRepository; import java.util.UUID; @Service @RequiredArgsConstructor public class StepService { - + private final StepRepository stepRepository; - + @Transactional public void deleteStep(UUID id) { if (!stepRepository.existsById(id)) { @@ -21,9 +21,9 @@ public class StepService { } stepRepository.deleteById(id); } - + public Step getStepById(UUID id) { return stepRepository.findById(id) - .orElseThrow(() -> new RuntimeException("Step not found with id: " + id)); + .orElseThrow(() -> new RuntimeException("Step not found with id: " + id)); } } diff --git a/src/main/java/xyz/pkay/simpleWf/core/service/TaskService.java b/src/main/java/xyz/pkay/veloflow/core/service/TaskService.java similarity index 85% rename from src/main/java/xyz/pkay/simpleWf/core/service/TaskService.java rename to src/main/java/xyz/pkay/veloflow/core/service/TaskService.java index 7637ca2..6705feb 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/service/TaskService.java +++ b/src/main/java/xyz/pkay/veloflow/core/service/TaskService.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.core.service; +package xyz.pkay.veloflow.core.service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import xyz.pkay.simpleWf.core.data.model.Task; -import xyz.pkay.simpleWf.core.data.repository.TaskRepository; +import xyz.pkay.veloflow.core.data.model.Task; +import xyz.pkay.veloflow.core.data.repository.TaskRepository; import java.util.List; diff --git a/src/main/java/xyz/pkay/simpleWf/core/service/WorkflowInstanceService.java b/src/main/java/xyz/pkay/veloflow/core/service/WorkflowInstanceService.java similarity index 93% rename from src/main/java/xyz/pkay/simpleWf/core/service/WorkflowInstanceService.java rename to src/main/java/xyz/pkay/veloflow/core/service/WorkflowInstanceService.java index 1139b12..0c3f586 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/service/WorkflowInstanceService.java +++ b/src/main/java/xyz/pkay/veloflow/core/service/WorkflowInstanceService.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.core.service; +package xyz.pkay.veloflow.core.service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import xyz.pkay.simpleWf.core.data.model.*; -import xyz.pkay.simpleWf.core.data.repository.WorkflowInstanceRepository; +import xyz.pkay.veloflow.core.data.model.*; +import xyz.pkay.veloflow.core.data.repository.WorkflowInstanceRepository; import java.time.LocalDateTime; import java.util.UUID; diff --git a/src/main/java/xyz/pkay/simpleWf/core/service/WorkflowService.java b/src/main/java/xyz/pkay/veloflow/core/service/WorkflowService.java similarity index 76% rename from src/main/java/xyz/pkay/simpleWf/core/service/WorkflowService.java rename to src/main/java/xyz/pkay/veloflow/core/service/WorkflowService.java index 9640d88..3953805 100644 --- a/src/main/java/xyz/pkay/simpleWf/core/service/WorkflowService.java +++ b/src/main/java/xyz/pkay/veloflow/core/service/WorkflowService.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.core.service; +package xyz.pkay.veloflow.core.service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import xyz.pkay.simpleWf.core.data.model.Workflow; -import xyz.pkay.simpleWf.core.data.repository.WorkflowRepository; +import xyz.pkay.veloflow.core.data.model.Workflow; +import xyz.pkay.veloflow.core.data.repository.WorkflowRepository; import java.util.List; import java.util.UUID; @@ -30,17 +30,19 @@ public class WorkflowService { repository.deleteById(id); } + @Transactional(readOnly = true) public List getAllWorkflows() { return repository.findAll(); } + @Transactional(readOnly = true) public Workflow getWorkflowById(UUID id) { return repository.findById(id).orElseThrow(() -> new RuntimeException("Workflow not found with id: " + id)); } public Workflow getWorkflowWithStepsById(UUID id) { - return repository.findByIdWithSteps(id).orElseThrow(() -> new RuntimeException("Workflow not found with id: " + id)); + return repository.findByIdWithFullDetails(id).orElseThrow(() -> new RuntimeException("Workflow not found with id: " + id)); } @Transactional @@ -51,11 +53,13 @@ public class WorkflowService { existingWorkflow.setStatus(workflow.getStatus()); if (workflow.getSteps() != null) { existingWorkflow.getSteps().clear(); - existingWorkflow.getSteps().addAll(workflow.getSteps().stream().peek(s -> s.setWorkflow(existingWorkflow)).toList()); + existingWorkflow.getSteps().addAll(workflow.getSteps()); + existingWorkflow.getSteps().forEach(s -> s.setWorkflow(existingWorkflow)); } if (workflow.getTransitions() != null) { existingWorkflow.getTransitions().clear(); - existingWorkflow.getTransitions().addAll(workflow.getTransitions().stream().peek(t -> t.setWorkflow(existingWorkflow)).toList()); + existingWorkflow.getTransitions().addAll(workflow.getTransitions()); + existingWorkflow.getTransitions().forEach(t -> t.setWorkflow(existingWorkflow)); } return repository.save(existingWorkflow); diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/controller/StepEditorController.java b/src/main/java/xyz/pkay/veloflow/editor/api/controller/StepEditorController.java similarity index 88% rename from src/main/java/xyz/pkay/simpleWf/editor/api/controller/StepEditorController.java rename to src/main/java/xyz/pkay/veloflow/editor/api/controller/StepEditorController.java index fae1efd..b109c31 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/controller/StepEditorController.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/controller/StepEditorController.java @@ -1,12 +1,12 @@ -package xyz.pkay.simpleWf.editor.api.controller; +package xyz.pkay.veloflow.editor.api.controller; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import xyz.pkay.simpleWf.editor.api.dto.StepDto; -import xyz.pkay.simpleWf.editor.service.StepEditorService; +import xyz.pkay.veloflow.editor.api.dto.StepDto; +import xyz.pkay.veloflow.editor.service.StepEditorService; import java.util.List; import java.util.UUID; @@ -17,30 +17,30 @@ import java.util.UUID; @Tags({@Tag(name = "Steps"), @Tag(name = "Editor")}) public class StepEditorController { - + private final StepEditorService stepEditorService; - + @PostMapping("/Workflows/{workflowId}") public ResponseEntity create(@PathVariable UUID workflowId, @RequestBody StepDto stepDto) { return ResponseEntity.ok(stepEditorService.createStep(workflowId, stepDto)); } - + @DeleteMapping("/{id}") public ResponseEntity delete(@PathVariable UUID id) { stepEditorService.deleteStep(id); return ResponseEntity.noContent().build(); } - + @GetMapping("/{id}") public ResponseEntity getById(@PathVariable UUID id) { return ResponseEntity.ok(stepEditorService.getStepById(id)); } - + @GetMapping("/Workflows/{workflowId}") public List listByWorkflow(@PathVariable UUID workflowId) { return stepEditorService.getStepsByWorkflowId(workflowId); } - + @PutMapping("/{id}") public ResponseEntity update(@PathVariable UUID id, @RequestBody StepDto stepDto) { return ResponseEntity.ok(stepEditorService.updateStep(id, stepDto)); diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/controller/WorkflowEditorController.java b/src/main/java/xyz/pkay/veloflow/editor/api/controller/WorkflowEditorController.java similarity index 53% rename from src/main/java/xyz/pkay/simpleWf/editor/api/controller/WorkflowEditorController.java rename to src/main/java/xyz/pkay/veloflow/editor/api/controller/WorkflowEditorController.java index 653725e..2bbd215 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/controller/WorkflowEditorController.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/controller/WorkflowEditorController.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.editor.api.controller; +package xyz.pkay.veloflow.editor.api.controller; import io.swagger.v3.oas.annotations.tags.Tag; @@ -6,8 +6,8 @@ import io.swagger.v3.oas.annotations.tags.Tags; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import xyz.pkay.simpleWf.editor.api.dto.WorkflowDto; -import xyz.pkay.simpleWf.editor.service.WorkflowEditorService; +import xyz.pkay.veloflow.editor.api.dto.WorkflowDto; +import xyz.pkay.veloflow.editor.service.WorkflowEditorService; import java.util.List; import java.util.UUID; @@ -17,43 +17,55 @@ import java.util.UUID; @RequiredArgsConstructor @Tags({@Tag(name = "Workflows"), @Tag(name = "Editor")}) public class WorkflowEditorController { - + private final WorkflowEditorService workflowEditorService; - + @PostMapping public ResponseEntity create(@RequestBody WorkflowDto workflowDto) { return ResponseEntity.ok(workflowEditorService.createWorkflow(workflowDto)); } - - + + @DeleteMapping("/{id}") public ResponseEntity delete(@PathVariable UUID id) { workflowEditorService.deleteWorkflow(id); return ResponseEntity.noContent().build(); } - - + + @GetMapping("/{id}/export/bpmn") + public ResponseEntity exportToBpmn(@PathVariable UUID id) throws Exception { + String bpmnXml = workflowEditorService.exportWorkflowToBpmn(id); + return ResponseEntity.ok() + .header("Content-Type", "application/xml") + .body(bpmnXml); + } + @GetMapping("/{id}") public ResponseEntity getById(@PathVariable UUID id) throws InterruptedException { return ResponseEntity.ok(workflowEditorService.getWorkflowById(id)); } - - + + @PostMapping("/import/bpmn") + public ResponseEntity importFromBpmn(@RequestBody String bpmnXml) throws Exception { + return ResponseEntity.ok(workflowEditorService.importWorkflowFromBpmn(bpmnXml)); + } + + @GetMapping public List list() { return workflowEditorService.getAllWorkflows(); } - + @PutMapping("/{id}") public ResponseEntity update(@PathVariable UUID id, @RequestBody WorkflowDto workflowDto) { WorkflowDto updatedDto = WorkflowDto.builder() - .createdAt(workflowDto.getCreatedAt()) - .id(id) - .name(workflowDto.getName()) - .status(workflowDto.getStatus()) - .steps(workflowDto.getSteps()) - .transitions(workflowDto.getTransitions()) - .build(); + .createdAt(workflowDto.getCreatedAt()) + .id(id) + .name(workflowDto.getName()) + .status(workflowDto.getStatus()) + .steps(workflowDto.getSteps()) + .transitions(workflowDto.getTransitions()) + .build(); return ResponseEntity.ok(workflowEditorService.updateWorkflow(id, updatedDto)); } } \ No newline at end of file diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/AnchorDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/AnchorDto.java similarity index 71% rename from src/main/java/xyz/pkay/simpleWf/editor/api/dto/AnchorDto.java rename to src/main/java/xyz/pkay/veloflow/editor/api/dto/AnchorDto.java index a551792..7a030d3 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/AnchorDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/AnchorDto.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.editor.api.dto; +package xyz.pkay.veloflow.editor.api.dto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import xyz.pkay.simpleWf.editor.model.enums.Side; +import xyz.pkay.veloflow.editor.model.enums.Side; @Builder @Data @@ -12,5 +12,6 @@ import xyz.pkay.simpleWf.editor.model.enums.Side; @AllArgsConstructor public class AnchorDto { private Side side; + private Integer sideIndex; } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/PositionDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/PositionDto.java similarity index 83% rename from src/main/java/xyz/pkay/simpleWf/editor/api/dto/PositionDto.java rename to src/main/java/xyz/pkay/veloflow/editor/api/dto/PositionDto.java index 4bf6e53..a7b9060 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/PositionDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/PositionDto.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.editor.api.dto; +package xyz.pkay.veloflow.editor.api.dto; import lombok.AllArgsConstructor; import lombok.Builder; @@ -11,5 +11,6 @@ import lombok.NoArgsConstructor; @AllArgsConstructor public class PositionDto { private Integer x; + private Integer y; } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/StepDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/StepDto.java similarity index 80% rename from src/main/java/xyz/pkay/simpleWf/editor/api/dto/StepDto.java rename to src/main/java/xyz/pkay/veloflow/editor/api/dto/StepDto.java index 633367e..2eaff57 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/StepDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/StepDto.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.editor.api.dto; +package xyz.pkay.veloflow.editor.api.dto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import xyz.pkay.simpleWf.core.data.model.*; +import xyz.pkay.veloflow.core.data.model.*; import java.util.UUID; @@ -14,13 +14,22 @@ import java.util.UUID; @AllArgsConstructor public class StepDto { private EventDefinition eventDefinition; + private EventTypes eventType; + private String executorClassName; + private GatewaySubTypes gatewaySubType; + private UUID id; + private String name; + private Integer order; + private PositionDto position; + private TaskSubTypes taskSubType; + private StepTypes type; } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/TaskDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/TaskDto.java similarity index 92% rename from src/main/java/xyz/pkay/simpleWf/editor/api/dto/TaskDto.java rename to src/main/java/xyz/pkay/veloflow/editor/api/dto/TaskDto.java index c1edc98..c067c7b 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/TaskDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/TaskDto.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.editor.api.dto; +package xyz.pkay.veloflow.editor.api.dto; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/TransitionDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/TransitionDto.java similarity index 86% rename from src/main/java/xyz/pkay/simpleWf/editor/api/dto/TransitionDto.java rename to src/main/java/xyz/pkay/veloflow/editor/api/dto/TransitionDto.java index 8c52c94..e1d6ce7 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/TransitionDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/TransitionDto.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.editor.api.dto; +package xyz.pkay.veloflow.editor.api.dto; import lombok.AllArgsConstructor; import lombok.Builder; @@ -13,12 +13,20 @@ import java.util.UUID; @AllArgsConstructor public class TransitionDto { private String actionName; + private String actionValue; + private UUID currentStepId; + private AnchorDto fromAnchor; + private UUID id; + private String name; + private UUID nextStepId; + private AnchorDto toAnchor; + private java.util.List waypoints; } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/WorkflowDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/WorkflowDto.java similarity index 87% rename from src/main/java/xyz/pkay/simpleWf/editor/api/dto/WorkflowDto.java rename to src/main/java/xyz/pkay/veloflow/editor/api/dto/WorkflowDto.java index 47f4412..141607c 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/WorkflowDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/WorkflowDto.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.editor.api.dto; +package xyz.pkay.veloflow.editor.api.dto; import lombok.AllArgsConstructor; import lombok.Builder; @@ -15,9 +15,14 @@ import java.util.UUID; @AllArgsConstructor public class WorkflowDto { private LocalDateTime createdAt; + private UUID id; + private String name; + private String status; + private List steps; + private List transitions; } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/WorkflowInstanceDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/WorkflowInstanceDto.java similarity index 84% rename from src/main/java/xyz/pkay/simpleWf/editor/api/dto/WorkflowInstanceDto.java rename to src/main/java/xyz/pkay/veloflow/editor/api/dto/WorkflowInstanceDto.java index de1d9dc..f3e60fa 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/api/dto/WorkflowInstanceDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/WorkflowInstanceDto.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.editor.api.dto; +package xyz.pkay.veloflow.editor.api.dto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import xyz.pkay.simpleWf.core.data.model.InstanceStatus; +import xyz.pkay.veloflow.core.data.model.InstanceStatus; import java.time.LocalDateTime; import java.util.List; diff --git a/src/main/java/xyz/pkay/simpleWf/editor/mapper/WorkflowMapper.java b/src/main/java/xyz/pkay/veloflow/editor/mapper/WorkflowMapper.java similarity index 95% rename from src/main/java/xyz/pkay/simpleWf/editor/mapper/WorkflowMapper.java rename to src/main/java/xyz/pkay/veloflow/editor/mapper/WorkflowMapper.java index a7f8fbc..b2f6498 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/mapper/WorkflowMapper.java +++ b/src/main/java/xyz/pkay/veloflow/editor/mapper/WorkflowMapper.java @@ -1,10 +1,10 @@ -package xyz.pkay.simpleWf.editor.mapper; +package xyz.pkay.veloflow.editor.mapper; import org.springframework.stereotype.Component; -import xyz.pkay.simpleWf.core.data.model.*; -import xyz.pkay.simpleWf.editor.api.dto.*; -import xyz.pkay.simpleWf.editor.model.Anchor; -import xyz.pkay.simpleWf.editor.model.Position; +import xyz.pkay.veloflow.core.data.model.*; +import xyz.pkay.veloflow.editor.api.dto.*; +import xyz.pkay.veloflow.editor.model.Anchor; +import xyz.pkay.veloflow.editor.model.Position; import java.util.stream.Collectors; @@ -145,14 +145,14 @@ public class WorkflowMapper { Step step = this.toEntity(s); step.setWorkflow(entity); return step; - }).collect(Collectors.toList())); + }).collect(Collectors.toSet())); } if (dto.getTransitions() != null) { entity.setTransitions(dto.getTransitions().stream().map(t -> { Transition transition = this.toEntity(t, entity); transition.setWorkflow(entity); return transition; - }).collect(Collectors.toList())); + }).collect(Collectors.toSet())); } return entity; } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/model/Anchor.java b/src/main/java/xyz/pkay/veloflow/editor/model/Anchor.java similarity index 83% rename from src/main/java/xyz/pkay/simpleWf/editor/model/Anchor.java rename to src/main/java/xyz/pkay/veloflow/editor/model/Anchor.java index 024de3e..a2d9df6 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/model/Anchor.java +++ b/src/main/java/xyz/pkay/veloflow/editor/model/Anchor.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.editor.model; +package xyz.pkay.veloflow.editor.model; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; @@ -8,7 +8,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import xyz.pkay.simpleWf.editor.model.enums.Side; +import xyz.pkay.veloflow.editor.model.enums.Side; @Embeddable @Getter @@ -16,10 +16,10 @@ import xyz.pkay.simpleWf.editor.model.enums.Side; @NoArgsConstructor @AllArgsConstructor public class Anchor { - + @Enumerated(EnumType.STRING) @Column(length = 10) private Side side; // top, left, right, bottom - + private Integer sideIndex; } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/model/Position.java b/src/main/java/xyz/pkay/veloflow/editor/model/Position.java similarity index 85% rename from src/main/java/xyz/pkay/simpleWf/editor/model/Position.java rename to src/main/java/xyz/pkay/veloflow/editor/model/Position.java index b8a682c..6edc9e3 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/model/Position.java +++ b/src/main/java/xyz/pkay/veloflow/editor/model/Position.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.editor.model; +package xyz.pkay.veloflow.editor.model; import jakarta.persistence.Embeddable; import lombok.AllArgsConstructor; @@ -12,8 +12,8 @@ import lombok.Setter; @NoArgsConstructor @AllArgsConstructor public class Position { - + private Integer x; - + private Integer y; } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/model/enums/Side.java b/src/main/java/xyz/pkay/veloflow/editor/model/enums/Side.java similarity index 85% rename from src/main/java/xyz/pkay/simpleWf/editor/model/enums/Side.java rename to src/main/java/xyz/pkay/veloflow/editor/model/enums/Side.java index 24c0d01..78e6c91 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/model/enums/Side.java +++ b/src/main/java/xyz/pkay/veloflow/editor/model/enums/Side.java @@ -1,11 +1,11 @@ -package xyz.pkay.simpleWf.editor.model.enums; +package xyz.pkay.veloflow.editor.model.enums; public enum Side { TOP, LEFT, RIGHT, BOTTOM; - + public static Side fromString(String side) { if (side == null) return null; try { diff --git a/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java b/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java new file mode 100644 index 0000000..ac4767b --- /dev/null +++ b/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java @@ -0,0 +1,309 @@ +package xyz.pkay.veloflow.editor.service; + +import org.springframework.stereotype.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import xyz.pkay.veloflow.core.data.model.EventTypes; +import xyz.pkay.veloflow.core.data.model.GatewaySubTypes; +import xyz.pkay.veloflow.core.data.model.StepTypes; +import xyz.pkay.veloflow.core.data.model.TaskSubTypes; +import xyz.pkay.veloflow.editor.api.dto.PositionDto; +import xyz.pkay.veloflow.editor.api.dto.StepDto; +import xyz.pkay.veloflow.editor.api.dto.TransitionDto; +import xyz.pkay.veloflow.editor.api.dto.WorkflowDto; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayInputStream; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Service +public class BpmnService { + + private static final String BPMNDI_NS = "http://www.omg.org/spec/BPMN/20100524/DI"; + + private static final String BPMN_NS = "http://www.omg.org/spec/BPMN/20100524/MODEL"; + + private static final String DC_NS = "http://www.omg.org/spec/DD/20100524/DC"; + + private static final String DI_NS = "http://www.omg.org/spec/DD/20100524/DI"; + + public String exportToBpmn(WorkflowDto workflow) throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.newDocument(); + + Element definitions = doc.createElementNS(BPMN_NS, "bpmn:definitions"); + definitions.setAttribute("xmlns:bpmn", BPMN_NS); + definitions.setAttribute("xmlns:bpmndi", BPMNDI_NS); + definitions.setAttribute("xmlns:dc", DC_NS); + definitions.setAttribute("xmlns:di", DI_NS); + definitions.setAttribute("targetNamespace", "http://bpmn.io/schema/bpmn"); + doc.appendChild(definitions); + + Element process = doc.createElementNS(BPMN_NS, "bpmn:process"); + process.setAttribute("id", "Process_" + (workflow.getId() != null ? workflow.getId() : UUID.randomUUID())); + process.setAttribute("isExecutable", "false"); + process.setAttribute("name", workflow.getName()); + definitions.appendChild(process); + + Element diagram = doc.createElementNS(BPMNDI_NS, "bpmndi:BPMNDiagram"); + diagram.setAttribute("id", "BPMNDiagram_1"); + definitions.appendChild(diagram); + + Element plane = doc.createElementNS(BPMNDI_NS, "bpmndi:BPMNPlane"); + plane.setAttribute("id", "BPMNPlane_1"); + plane.setAttribute("bpmnElement", process.getAttribute("id")); + diagram.appendChild(plane); + + Map stepIdToBpmnId = new HashMap<>(); + + for (StepDto step : workflow.getSteps()) { + String bpmnId = getBpmnId(step); + stepIdToBpmnId.put(step.getId(), bpmnId); + Element stepEl = doc.createElementNS(BPMN_NS, "bpmn:" + getBpmnElementName(step)); + stepEl.setAttribute("id", bpmnId); + stepEl.setAttribute("name", step.getName()); + process.appendChild(stepEl); + + // Add DI Shape + Element shape = doc.createElementNS(BPMNDI_NS, "bpmndi:BPMNShape"); + shape.setAttribute("id", bpmnId + "_di"); + shape.setAttribute("bpmnElement", bpmnId); + plane.appendChild(shape); + + Element bounds = doc.createElementNS(DC_NS, "dc:Bounds"); + int x = step.getPosition() != null ? step.getPosition().getX() : 0; + int y = step.getPosition() != null ? step.getPosition().getY() : 0; + bounds.setAttribute("x", String.valueOf(x)); + bounds.setAttribute("y", String.valueOf(y)); + bounds.setAttribute("width", "100"); + bounds.setAttribute("height", "80"); + shape.appendChild(bounds); + } + + for (TransitionDto transition : workflow.getTransitions()) { + String transId = "Flow_" + (transition.getId() != null ? transition.getId() : UUID.randomUUID()); + Element flow = doc.createElementNS(BPMN_NS, "bpmn:sequenceFlow"); + flow.setAttribute("id", transId); + flow.setAttribute("name", transition.getName()); + flow.setAttribute("sourceRef", stepIdToBpmnId.get(transition.getCurrentStepId())); + flow.setAttribute("targetRef", stepIdToBpmnId.get(transition.getNextStepId())); + process.appendChild(flow); + + // Add DI Edge + Element edge = doc.createElementNS(BPMNDI_NS, "bpmndi:BPMNEdge"); + edge.setAttribute("id", transId + "_di"); + edge.setAttribute("bpmnElement", transId); + plane.appendChild(edge); + + if (transition.getWaypoints() != null) { + for (PositionDto wp : transition.getWaypoints()) { + Element waypoint = doc.createElementNS(DI_NS, "di:waypoint"); + waypoint.setAttribute("x", String.valueOf(wp.getX())); + waypoint.setAttribute("y", String.valueOf(wp.getY())); + edge.appendChild(waypoint); + } + } + } + + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(doc), new StreamResult(writer)); + return writer.getBuffer().toString(); + } + + private String getBpmnElementName(StepDto step) { + if (step.getType() == StepTypes.EVENT) { + if (step.getEventType() == EventTypes.START_EVENT) return "startEvent"; + if (step.getEventType() == EventTypes.END_EVENT) return "endEvent"; + return "intermediateEvent"; + } + if (step.getType() == StepTypes.GATEWAY) { + if (step.getGatewaySubType() == GatewaySubTypes.EXCLUSIVE_GATEWAY) return "exclusiveGateway"; + if (step.getGatewaySubType() == GatewaySubTypes.PARALLEL_GATEWAY) return "parallelGateway"; + if (step.getGatewaySubType() == GatewaySubTypes.INCLUSIVE_GATEWAY) return "inclusiveGateway"; + if (step.getGatewaySubType() == GatewaySubTypes.EVENT_BASED_GATEWAY) return "eventBasedGateway"; + return "exclusiveGateway"; + } + if (step.getTaskSubType() != null) { + switch (step.getTaskSubType()) { + case USER_TASK: + return "userTask"; + case SERVICE_TASK: + return "serviceTask"; + case SCRIPT_TASK: + return "scriptTask"; + case MANUAL_TASK: + return "manualTask"; + case SEND_TASK: + return "sendTask"; + case RECEIVE_TASK: + return "receiveTask"; + case BUSINESS_RULE_TASK: + return "businessRuleTask"; + } + } + return "task"; + } + + private String getBpmnId(StepDto step) { + return "Step_" + step.getId(); + } + + public WorkflowDto importFromBpmn(String xml) throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.parse(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))); + + Element definitions = doc.getDocumentElement(); + Element process = (Element) definitions.getElementsByTagNameNS(BPMN_NS, "process").item(0); + String name = process.getAttribute("name"); + + WorkflowDto workflow = WorkflowDto.builder() + .name(name) + .steps(new ArrayList<>()) + .transitions(new ArrayList<>()) + .status("DRAFT") + .build(); + + Map bpmnIdToStepId = new HashMap<>(); + + String[] elementTypes = {"startEvent", "endEvent", "intermediateEvent", "task", "userTask", "serviceTask", "scriptTask", "manualTask", "sendTask", "receiveTask", "businessRuleTask", "exclusiveGateway", "parallelGateway", "inclusiveGateway", "eventBasedGateway"}; + + for (String type : elementTypes) { + NodeList nodes = process.getElementsByTagNameNS(BPMN_NS, type); + for (int i = 0; i < nodes.getLength(); i++) { + Element el = (Element) nodes.item(i); + StepDto step = parseStep(el, type, doc); + workflow.getSteps().add(step); + bpmnIdToStepId.put(el.getAttribute("id"), step.getId()); + } + } + + NodeList flows = process.getElementsByTagNameNS(BPMN_NS, "sequenceFlow"); + for (int i = 0; i < flows.getLength(); i++) { + Element el = (Element) flows.item(i); + TransitionDto transition = parseTransition(el, bpmnIdToStepId, doc); + if (transition != null) { + workflow.getTransitions().add(transition); + } + } + + return workflow; + } + + private StepDto parseStep(Element el, String bpmnType, Document doc) { + UUID id = UUID.randomUUID(); + String bpmnId = el.getAttribute("id"); + try { + if (bpmnId.contains("-")) { + id = UUID.fromString(bpmnId.replace("Step_", "")); + } + } catch (Exception ignored) {} + + StepDto step = StepDto.builder() + .id(id) + .name(el.getAttribute("name")) + .build(); + + if (bpmnType.contains("Event")) { + step.setType(StepTypes.EVENT); + if (bpmnType.equals("startEvent")) step.setEventType(EventTypes.START_EVENT); + else if (bpmnType.equals("endEvent")) step.setEventType(EventTypes.END_EVENT); + else step.setEventType(EventTypes.INTERMEDIATE_EVENT); + } else if (bpmnType.contains("Gateway")) { + step.setType(StepTypes.GATEWAY); + if (bpmnType.equals("exclusiveGateway")) step.setGatewaySubType(GatewaySubTypes.EXCLUSIVE_GATEWAY); + else if (bpmnType.equals("parallelGateway")) step.setGatewaySubType(GatewaySubTypes.PARALLEL_GATEWAY); + else if (bpmnType.equals("inclusiveGateway")) step.setGatewaySubType(GatewaySubTypes.INCLUSIVE_GATEWAY); + else if (bpmnType.equals("eventBasedGateway")) step.setGatewaySubType(GatewaySubTypes.EVENT_BASED_GATEWAY); + } else { + step.setType(StepTypes.TASK); + if (bpmnType.equals("userTask")) step.setTaskSubType(TaskSubTypes.USER_TASK); + else if (bpmnType.equals("serviceTask")) step.setTaskSubType(TaskSubTypes.SERVICE_TASK); + else if (bpmnType.equals("scriptTask")) step.setTaskSubType(TaskSubTypes.SCRIPT_TASK); + else if (bpmnType.equals("manualTask")) step.setTaskSubType(TaskSubTypes.MANUAL_TASK); + else if (bpmnType.equals("sendTask")) step.setTaskSubType(TaskSubTypes.SEND_TASK); + else if (bpmnType.equals("receiveTask")) step.setTaskSubType(TaskSubTypes.RECEIVE_TASK); + else if (bpmnType.equals("businessRuleTask")) step.setTaskSubType(TaskSubTypes.BUSINESS_RULE_TASK); + } + + // Parse DI for position + NodeList shapes = doc.getElementsByTagNameNS(BPMNDI_NS, "BPMNShape"); + for (int i = 0; i < shapes.getLength(); i++) { + Element shape = (Element) shapes.item(i); + if (shape.getAttribute("bpmnElement").equals(bpmnId)) { + Element bounds = (Element) shape.getElementsByTagNameNS(DC_NS, "Bounds").item(0); + if (bounds != null) { + step.setPosition(PositionDto.builder() + .x((int) Double.parseDouble(bounds.getAttribute("x"))) + .y((int) Double.parseDouble(bounds.getAttribute("y"))) + .build()); + } + break; + } + } + + return step; + } + + private TransitionDto parseTransition(Element el, Map bpmnIdToStepId, Document doc) { + String sourceRef = el.getAttribute("sourceRef"); + String targetRef = el.getAttribute("targetRef"); + if (!bpmnIdToStepId.containsKey(sourceRef) || !bpmnIdToStepId.containsKey(targetRef)) { + return null; + } + + UUID id = UUID.randomUUID(); + String bpmnId = el.getAttribute("id"); + try { + if (bpmnId.contains("-")) { + id = UUID.fromString(bpmnId.replace("Flow_", "")); + } + } catch (Exception ignored) {} + + TransitionDto transition = TransitionDto.builder() + .id(id) + .name(el.getAttribute("name")) + .currentStepId(bpmnIdToStepId.get(sourceRef)) + .nextStepId(bpmnIdToStepId.get(targetRef)) + .waypoints(new ArrayList<>()) + .build(); + + // Parse DI for waypoints + NodeList edges = doc.getElementsByTagNameNS(BPMNDI_NS, "BPMNEdge"); + for (int i = 0; i < edges.getLength(); i++) { + Element edge = (Element) edges.item(i); + if (edge.getAttribute("bpmnElement").equals(bpmnId)) { + NodeList waypoints = edge.getElementsByTagNameNS(DI_NS, "waypoint"); + for (int j = 0; j < waypoints.getLength(); j++) { + Element wp = (Element) waypoints.item(j); + transition.getWaypoints().add(PositionDto.builder() + .x((int) Double.parseDouble(wp.getAttribute("x"))) + .y((int) Double.parseDouble(wp.getAttribute("y"))) + .build()); + } + break; + } + } + + return transition; + } +} diff --git a/src/main/java/xyz/pkay/simpleWf/editor/service/StepEditorService.java b/src/main/java/xyz/pkay/veloflow/editor/service/StepEditorService.java similarity index 65% rename from src/main/java/xyz/pkay/simpleWf/editor/service/StepEditorService.java rename to src/main/java/xyz/pkay/veloflow/editor/service/StepEditorService.java index f77dab3..9ec7fc7 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/service/StepEditorService.java +++ b/src/main/java/xyz/pkay/veloflow/editor/service/StepEditorService.java @@ -1,14 +1,14 @@ -package xyz.pkay.simpleWf.editor.service; +package xyz.pkay.veloflow.editor.service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import xyz.pkay.simpleWf.core.data.model.Step; -import xyz.pkay.simpleWf.core.data.model.Workflow; -import xyz.pkay.simpleWf.core.data.repository.StepRepository; -import xyz.pkay.simpleWf.core.data.repository.WorkflowRepository; -import xyz.pkay.simpleWf.editor.api.dto.StepDto; -import xyz.pkay.simpleWf.editor.mapper.WorkflowMapper; +import xyz.pkay.veloflow.core.data.model.Step; +import xyz.pkay.veloflow.core.data.model.Workflow; +import xyz.pkay.veloflow.core.data.repository.StepRepository; +import xyz.pkay.veloflow.core.data.repository.WorkflowRepository; +import xyz.pkay.veloflow.editor.api.dto.StepDto; +import xyz.pkay.veloflow.editor.mapper.WorkflowMapper; import java.util.List; import java.util.UUID; @@ -17,21 +17,23 @@ import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class StepEditorService { - + private final WorkflowMapper mapper; + private final StepRepository stepRepository; + private final WorkflowRepository workflowRepository; - + @Transactional public StepDto createStep(UUID workflowId, StepDto stepDto) { Workflow workflow = workflowRepository.findById(workflowId) - .orElseThrow(() -> new RuntimeException("Workflow not found with id: " + workflowId)); - + .orElseThrow(() -> new RuntimeException("Workflow not found with id: " + workflowId)); + Step step = mapper.toEntity(stepDto); step.setWorkflow(workflow); return mapper.toDto(stepRepository.save(step)); } - + @Transactional public void deleteStep(UUID id) { if (!stepRepository.existsById(id)) { @@ -39,26 +41,26 @@ public class StepEditorService { } stepRepository.deleteById(id); } - + public StepDto getStepById(UUID id) { return stepRepository.findById(id) - .map(mapper::toDto) - .orElseThrow(() -> new RuntimeException("Step not found with id: " + id)); + .map(mapper::toDto) + .orElseThrow(() -> new RuntimeException("Step not found with id: " + id)); } - + public List getStepsByWorkflowId(UUID workflowId) { Workflow workflow = workflowRepository.findById(workflowId) - .orElseThrow(() -> new RuntimeException("Workflow not found with id: " + workflowId)); + .orElseThrow(() -> new RuntimeException("Workflow not found with id: " + workflowId)); return workflow.getSteps().stream() - .map(mapper::toDto) - .collect(Collectors.toList()); + .map(mapper::toDto) + .collect(Collectors.toList()); } - + @Transactional public StepDto updateStep(UUID id, StepDto stepDto) { Step existingStep = stepRepository.findById(id) - .orElseThrow(() -> new RuntimeException("Step not found with id: " + id)); - + .orElseThrow(() -> new RuntimeException("Step not found with id: " + id)); + existingStep.setName(stepDto.getName()); existingStep.setType(stepDto.getType()); existingStep.setOrder(stepDto.getOrder()); @@ -68,7 +70,7 @@ public class StepEditorService { existingStep.setGatewaySubType(stepDto.getGatewaySubType()); existingStep.setExecutorClassName(stepDto.getExecutorClassName()); existingStep.setEventDefinition(stepDto.getEventDefinition()); - + return mapper.toDto(stepRepository.save(existingStep)); } } diff --git a/src/main/java/xyz/pkay/simpleWf/editor/service/WorkflowEditorService.java b/src/main/java/xyz/pkay/veloflow/editor/service/WorkflowEditorService.java similarity index 55% rename from src/main/java/xyz/pkay/simpleWf/editor/service/WorkflowEditorService.java rename to src/main/java/xyz/pkay/veloflow/editor/service/WorkflowEditorService.java index 2dc87f9..0af4b04 100644 --- a/src/main/java/xyz/pkay/simpleWf/editor/service/WorkflowEditorService.java +++ b/src/main/java/xyz/pkay/veloflow/editor/service/WorkflowEditorService.java @@ -1,11 +1,11 @@ -package xyz.pkay.simpleWf.editor.service; +package xyz.pkay.veloflow.editor.service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import xyz.pkay.simpleWf.core.service.WorkflowService; -import xyz.pkay.simpleWf.editor.api.dto.WorkflowDto; -import xyz.pkay.simpleWf.editor.mapper.WorkflowMapper; +import xyz.pkay.veloflow.core.service.WorkflowService; +import xyz.pkay.veloflow.editor.api.dto.WorkflowDto; +import xyz.pkay.veloflow.editor.mapper.WorkflowMapper; import java.util.List; import java.util.UUID; @@ -14,31 +14,45 @@ import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class WorkflowEditorService { - + + private final BpmnService bpmnService; + private final WorkflowMapper mapper; + private final WorkflowService workflowService; - - + @Transactional public WorkflowDto createWorkflow(WorkflowDto workflowDto) { return mapper.toDto(workflowService.createWorkflow(mapper.toEntity(workflowDto))); } - - + @Transactional public void deleteWorkflow(UUID id) { workflowService.deleteWorkflow(id); } - + + @Transactional(readOnly = true) + public String exportWorkflowToBpmn(UUID id) throws Exception { + WorkflowDto workflowDto = getWorkflowById(id); + return bpmnService.exportToBpmn(workflowDto); + } + + @Transactional(readOnly = true) public List getAllWorkflows() { return workflowService.getAllWorkflows().stream().map(mapper::toDto).collect(Collectors.toList()); } - - + + @Transactional(readOnly = true) public WorkflowDto getWorkflowById(UUID id) { - return mapper.toDto(workflowService.getWorkflowById(id)); + return mapper.toDto(workflowService.getWorkflowWithStepsById(id)); } - + + @Transactional + public WorkflowDto importWorkflowFromBpmn(String bpmnXml) throws Exception { + WorkflowDto workflowDto = bpmnService.importFromBpmn(bpmnXml); + return createWorkflow(workflowDto); + } + @Transactional public WorkflowDto updateWorkflow(UUID id, WorkflowDto workflowDto) { return mapper.toDto(workflowService.updateWorkflow(id, mapper.toEntity(workflowDto))); diff --git a/src/main/java/xyz/pkay/simpleWf/exception/GlobalExceptionHandler.java b/src/main/java/xyz/pkay/veloflow/exception/GlobalExceptionHandler.java similarity index 95% rename from src/main/java/xyz/pkay/simpleWf/exception/GlobalExceptionHandler.java rename to src/main/java/xyz/pkay/veloflow/exception/GlobalExceptionHandler.java index f5752a3..98643be 100644 --- a/src/main/java/xyz/pkay/simpleWf/exception/GlobalExceptionHandler.java +++ b/src/main/java/xyz/pkay/veloflow/exception/GlobalExceptionHandler.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.exception; +package xyz.pkay.veloflow.exception; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,17 +11,9 @@ import java.util.Map; @RestControllerAdvice public class GlobalExceptionHandler { - + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); - - @ExceptionHandler(RuntimeException.class) - public ResponseEntity handleRuntimeException(RuntimeException ex) { - log.error("Runtime exception occurred: ", ex); - return ResponseEntity - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(Map.of("error", ex.getMessage())); - } - + @ExceptionHandler(org.springframework.http.converter.HttpMessageNotReadableException.class) public ResponseEntity handleHttpMessageNotReadableException(org.springframework.http.converter.HttpMessageNotReadableException ex) { log.error("JSON parsing error: ", ex); @@ -29,4 +21,12 @@ public class GlobalExceptionHandler { .status(HttpStatus.BAD_REQUEST) .body(Map.of("error", ex.getMessage())); } + + @ExceptionHandler(RuntimeException.class) + public ResponseEntity handleRuntimeException(RuntimeException ex) { + log.error("Runtime exception occurred: ", ex); + return ResponseEntity + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(Map.of("error", ex.getMessage())); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f9a0a64..31338fb 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,18 +9,20 @@ spring: username: ${DB_USER} password: ${DB_PASSWORD} hikari: - max-lifetime: 150000 - keepalive-time: 30000 - minimum-idle: 2 - maximum-pool-size: 4 - validation-timeout: 500 - connection-test-query: SELECT 1 + max-lifetime: 60000 + keepalive-time: 25000 + minimum-idle: 4 + maximum-pool-size: 8 + validation-timeout: 2000 + leak-detection-threshold: 5000 jpa: generate-ddl: on hibernate: ddl-auto: update show-sql: ${SHOW_SQL} + properties: + hibernate.default_batch_fetch_size: 50 logging: level: web: info diff --git a/src/test/java/xyz/pkay/simpleWf/api/controller/StepCreationTest.java b/src/test/java/xyz/pkay/veloflow/api/controller/StepCreationTest.java similarity index 70% rename from src/test/java/xyz/pkay/simpleWf/api/controller/StepCreationTest.java rename to src/test/java/xyz/pkay/veloflow/api/controller/StepCreationTest.java index 88a1f65..8e088cc 100644 --- a/src/test/java/xyz/pkay/simpleWf/api/controller/StepCreationTest.java +++ b/src/test/java/xyz/pkay/veloflow/api/controller/StepCreationTest.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.api.controller; +package xyz.pkay.veloflow.api.controller; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -16,21 +16,21 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @AutoConfigureMockMvc @ActiveProfiles("test") public class StepCreationTest { - + @Autowired private MockMvc mockMvc; - + @Test public void testCreateStepWithEventDefinition() throws Exception { String workflowPayload = "{\"name\":\"Test Workflow\"}"; String workflowResponse = mockMvc.perform(post("/Workflows") - .contentType(MediaType.APPLICATION_JSON) - .content(workflowPayload)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - + .contentType(MediaType.APPLICATION_JSON) + .content(workflowPayload)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + String workflowId = workflowResponse.split("\"id\":\"")[1].split("\"")[0]; - + String stepPayload = "{" + "\"name\":\"Start Event\"," + "\"type\":\"EVENT\"," + @@ -39,11 +39,11 @@ public class StepCreationTest { "\"position\":{\"x\":100,\"y\":100}," + "\"eventDefinition\":\"MESSAGE\"" + "}"; - + mockMvc.perform(post("/Steps/Workflows/" + workflowId) - .contentType(MediaType.APPLICATION_JSON) - .content(stepPayload)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventDefinition").value("MESSAGE")); + .contentType(MediaType.APPLICATION_JSON) + .content(stepPayload)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.eventDefinition").value("MESSAGE")); } } diff --git a/src/test/java/xyz/pkay/simpleWf/api/controller/WorkflowControllerTest.java b/src/test/java/xyz/pkay/veloflow/api/controller/WorkflowControllerTest.java similarity index 82% rename from src/test/java/xyz/pkay/simpleWf/api/controller/WorkflowControllerTest.java rename to src/test/java/xyz/pkay/veloflow/api/controller/WorkflowControllerTest.java index 865030e..ea05c3e 100644 --- a/src/test/java/xyz/pkay/simpleWf/api/controller/WorkflowControllerTest.java +++ b/src/test/java/xyz/pkay/veloflow/api/controller/WorkflowControllerTest.java @@ -1,4 +1,4 @@ -package xyz.pkay.simpleWf.api.controller; +package xyz.pkay.veloflow.api.controller; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -13,18 +13,18 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SpringBootTest @AutoConfigureMockMvc public class WorkflowControllerTest { - + @Autowired private MockMvc mockMvc; - + @Test public void testUpdateWorkflowWithInvalidPayload() throws Exception { String workflowId = "fdc5752a-fe74-4377-8eab-638fc6e073d7"; String payload = "{\"steps\":[{\"name\":\"Step 1\",\"type\":\"default\",\"order\":0,\"position\":{\"x\":100,\"y\":100}},{\"name\":\"Step 2\",\"type\":\"default\",\"order\":1,\"position\":{\"x\":375,\"y\":278}}],\"transitions\":[{\"currentStepId\":\"Step 1\",\"actionName\":\"New Action\",\"actionValue\":\"Value\",\"fromAnchor\":{\"side\":\"RIGHT\",\"sideIndex\":2},\"nextStepId\":\"Step 2\",\"toAnchor\":{\"side\":\"TOP\",\"sideIndex\":1}}]}"; - + mockMvc.perform(put("/Workflows/" + workflowId) - .contentType(MediaType.APPLICATION_JSON) - .content(payload)) - .andExpect(status().isBadRequest()); // Expecting bad request due to deserialization error + .contentType(MediaType.APPLICATION_JSON) + .content(payload)) + .andExpect(status().isBadRequest()); // Expecting bad request due to deserialization error } } diff --git a/src/test/java/xyz/pkay/veloflow/editor/service/BpmnServiceTest.java b/src/test/java/xyz/pkay/veloflow/editor/service/BpmnServiceTest.java new file mode 100644 index 0000000..ec6ce84 --- /dev/null +++ b/src/test/java/xyz/pkay/veloflow/editor/service/BpmnServiceTest.java @@ -0,0 +1,83 @@ +package xyz.pkay.veloflow.editor.service; + +import org.junit.jupiter.api.Test; +import xyz.pkay.veloflow.core.data.model.EventTypes; +import xyz.pkay.veloflow.core.data.model.StepTypes; +import xyz.pkay.veloflow.editor.api.dto.PositionDto; +import xyz.pkay.veloflow.editor.api.dto.StepDto; +import xyz.pkay.veloflow.editor.api.dto.TransitionDto; +import xyz.pkay.veloflow.editor.api.dto.WorkflowDto; + +import java.util.List; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +public class BpmnServiceTest { + + private final BpmnService bpmnService = new BpmnService(); + + @Test + public void testExportAndImport() throws Exception { + UUID workflowId = UUID.randomUUID(); + UUID step1Id = UUID.randomUUID(); + UUID step2Id = UUID.randomUUID(); + + StepDto step1 = StepDto.builder() + .id(step1Id) + .name("Start Event") + .type(StepTypes.EVENT) + .eventType(EventTypes.START_EVENT) + .position(PositionDto.builder().x(100).y(100).build()) + .build(); + + StepDto step2 = StepDto.builder() + .id(step2Id) + .name("End Event") + .type(StepTypes.EVENT) + .eventType(EventTypes.END_EVENT) + .position(PositionDto.builder().x(300).y(100).build()) + .build(); + + TransitionDto transition = TransitionDto.builder() + .id(UUID.randomUUID()) + .name("Flow 1") + .currentStepId(step1Id) + .nextStepId(step2Id) + .waypoints(List.of(PositionDto.builder().x(150).y(100).build(), PositionDto.builder().x(250).y(100).build())) + .build(); + + WorkflowDto workflow = WorkflowDto.builder() + .id(workflowId) + .name("Test Workflow") + .steps(List.of(step1, step2)) + .transitions(List.of(transition)) + .build(); + + String bpmnXml = bpmnService.exportToBpmn(workflow); + assertNotNull(bpmnXml); + assertTrue(bpmnXml.contains("bpmn:startEvent")); + assertTrue(bpmnXml.contains("bpmn:endEvent")); + assertTrue(bpmnXml.contains("bpmn:sequenceFlow")); + assertTrue(bpmnXml.contains("Test Workflow")); + + WorkflowDto importedWorkflow = bpmnService.importFromBpmn(bpmnXml); + assertEquals("Test Workflow", importedWorkflow.getName()); + assertEquals(2, importedWorkflow.getSteps().size()); + assertEquals(1, importedWorkflow.getTransitions().size()); + + StepDto importedStep1 = importedWorkflow.getSteps().stream().filter(s -> s.getEventType() == EventTypes.START_EVENT).findFirst().orElseThrow(); + assertEquals("Start Event", importedStep1.getName()); + assertEquals(100, importedStep1.getPosition().getX()); + + StepDto importedStep2 = importedWorkflow.getSteps().stream().filter(s -> s.getEventType() == EventTypes.END_EVENT).findFirst().orElseThrow(); + assertEquals("End Event", importedStep2.getName()); + assertEquals(300, importedStep2.getPosition().getX()); + + TransitionDto importedTransition = importedWorkflow.getTransitions().get(0); + assertEquals("Flow 1", importedTransition.getName()); + assertEquals(importedStep1.getId(), importedTransition.getCurrentStepId()); + assertEquals(importedStep2.getId(), importedTransition.getNextStepId()); + assertEquals(2, importedTransition.getWaypoints().size()); + } +} -- GitLab From 228ef108ab5f0581f45db9e07f953c04a5fcc081 Mon Sep 17 00:00:00 2001 From: pratyush Date: Sat, 7 Mar 2026 22:38:01 +0000 Subject: [PATCH 2/3] Refactor BPMN import logic: handle BOM and quoted XML, replace `bpmnIdToStepId` with `bpmnIdToStep`, add position dimensions and anchors, remove unused `order` field from step and transition handling, and update corresponding tests and mappings --- .../pkay/veloflow/core/data/model/Step.java | 6 +- .../veloflow/editor/api/dto/PositionDto.java | 4 + .../pkay/veloflow/editor/api/dto/StepDto.java | 4 +- .../editor/mapper/WorkflowMapper.java | 15 +- .../veloflow/editor/service/BpmnService.java | 133 +++++++++++------- .../editor/service/StepEditorService.java | 2 +- .../editor/service/BpmnServiceTest.java | 24 ++++ 7 files changed, 130 insertions(+), 58 deletions(-) diff --git a/src/main/java/xyz/pkay/veloflow/core/data/model/Step.java b/src/main/java/xyz/pkay/veloflow/core/data/model/Step.java index 2ad9b33..24b49ac 100644 --- a/src/main/java/xyz/pkay/veloflow/core/data/model/Step.java +++ b/src/main/java/xyz/pkay/veloflow/core/data/model/Step.java @@ -29,9 +29,9 @@ public class Step { @Column(nullable = false) private String name; - - @Column(name = "step_order", nullable = false) - private Integer order; + +// @Column(name = "step_order", nullable = false) +// private Integer order; @Embedded private Position position; diff --git a/src/main/java/xyz/pkay/veloflow/editor/api/dto/PositionDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/PositionDto.java index a7b9060..d202dee 100644 --- a/src/main/java/xyz/pkay/veloflow/editor/api/dto/PositionDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/PositionDto.java @@ -10,6 +10,10 @@ import lombok.NoArgsConstructor; @NoArgsConstructor @AllArgsConstructor public class PositionDto { + private Integer height; + + private Integer width; + private Integer x; private Integer y; diff --git a/src/main/java/xyz/pkay/veloflow/editor/api/dto/StepDto.java b/src/main/java/xyz/pkay/veloflow/editor/api/dto/StepDto.java index 2eaff57..f9311fd 100644 --- a/src/main/java/xyz/pkay/veloflow/editor/api/dto/StepDto.java +++ b/src/main/java/xyz/pkay/veloflow/editor/api/dto/StepDto.java @@ -24,8 +24,8 @@ public class StepDto { private UUID id; private String name; - - private Integer order; + +// private Integer order; private PositionDto position; diff --git a/src/main/java/xyz/pkay/veloflow/editor/mapper/WorkflowMapper.java b/src/main/java/xyz/pkay/veloflow/editor/mapper/WorkflowMapper.java index b2f6498..67ff0ff 100644 --- a/src/main/java/xyz/pkay/veloflow/editor/mapper/WorkflowMapper.java +++ b/src/main/java/xyz/pkay/veloflow/editor/mapper/WorkflowMapper.java @@ -54,7 +54,7 @@ public class WorkflowMapper { .id(entity.getId()) .name(entity.getName()) .type(entity.getType()) - .order(entity.getOrder()) +// .order(entity.getOrder()) .position(toDto(entity.getPosition())) .eventType(entity.getEventType()) .taskSubType(entity.getTaskSubType()) @@ -154,6 +154,17 @@ public class WorkflowMapper { return transition; }).collect(Collectors.toSet())); } + + // If it's a new workflow, clear temporary IDs to avoid "detached entity" error in Hibernate + if (entity.getId() == null) { + if (entity.getSteps() != null) { + entity.getSteps().forEach(s -> s.setId(null)); + } + if (entity.getTransitions() != null) { + entity.getTransitions().forEach(t -> t.setId(null)); + } + } + return entity; } @@ -163,7 +174,7 @@ public class WorkflowMapper { entity.setId(dto.getId()); entity.setName(dto.getName()); entity.setType(dto.getType()); - entity.setOrder(dto.getOrder()); +// entity.setOrder(dto.getOrder()); entity.setPosition(toEntity(dto.getPosition())); entity.setEventType(dto.getEventType()); entity.setTaskSubType(dto.getTaskSubType()); diff --git a/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java b/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java index ac4767b..9c8f606 100644 --- a/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java +++ b/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java @@ -8,10 +8,8 @@ import xyz.pkay.veloflow.core.data.model.EventTypes; import xyz.pkay.veloflow.core.data.model.GatewaySubTypes; import xyz.pkay.veloflow.core.data.model.StepTypes; import xyz.pkay.veloflow.core.data.model.TaskSubTypes; -import xyz.pkay.veloflow.editor.api.dto.PositionDto; -import xyz.pkay.veloflow.editor.api.dto.StepDto; -import xyz.pkay.veloflow.editor.api.dto.TransitionDto; -import xyz.pkay.veloflow.editor.api.dto.WorkflowDto; +import xyz.pkay.veloflow.editor.api.dto.*; +import xyz.pkay.veloflow.editor.model.enums.Side; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -167,6 +165,17 @@ public class BpmnService { } public WorkflowDto importFromBpmn(String xml) throws Exception { + if (xml != null) { + xml = xml.trim(); + if (xml.startsWith("\uFEFF")) { + xml = xml.substring(1).trim(); + } + if (xml.startsWith("\"") && xml.endsWith("\"")) { + xml = xml.substring(1, xml.length() - 1); + xml = xml.replace("\\\"", "\"").replace("\\n", "\n").replace("\\r", "\r").replace("\\t", "\t"); + } + } + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); @@ -176,14 +185,9 @@ public class BpmnService { Element process = (Element) definitions.getElementsByTagNameNS(BPMN_NS, "process").item(0); String name = process.getAttribute("name"); - WorkflowDto workflow = WorkflowDto.builder() - .name(name) - .steps(new ArrayList<>()) - .transitions(new ArrayList<>()) - .status("DRAFT") - .build(); + WorkflowDto workflow = WorkflowDto.builder().name(name).steps(new ArrayList<>()).transitions(new ArrayList<>()).status("DRAFT").build(); - Map bpmnIdToStepId = new HashMap<>(); + Map bpmnIdToStep = new HashMap<>(); String[] elementTypes = {"startEvent", "endEvent", "intermediateEvent", "task", "userTask", "serviceTask", "scriptTask", "manualTask", "sendTask", "receiveTask", "businessRuleTask", "exclusiveGateway", "parallelGateway", "inclusiveGateway", "eventBasedGateway"}; @@ -192,16 +196,18 @@ public class BpmnService { for (int i = 0; i < nodes.getLength(); i++) { Element el = (Element) nodes.item(i); StepDto step = parseStep(el, type, doc); + step.setId(UUID.randomUUID()); workflow.getSteps().add(step); - bpmnIdToStepId.put(el.getAttribute("id"), step.getId()); + bpmnIdToStep.put(el.getAttribute("id"), step); } } NodeList flows = process.getElementsByTagNameNS(BPMN_NS, "sequenceFlow"); for (int i = 0; i < flows.getLength(); i++) { Element el = (Element) flows.item(i); - TransitionDto transition = parseTransition(el, bpmnIdToStepId, doc); + TransitionDto transition = parseTransition(el, bpmnIdToStep, doc); if (transition != null) { + transition.setId(UUID.randomUUID()); workflow.getTransitions().add(transition); } } @@ -210,18 +216,9 @@ public class BpmnService { } private StepDto parseStep(Element el, String bpmnType, Document doc) { - UUID id = UUID.randomUUID(); String bpmnId = el.getAttribute("id"); - try { - if (bpmnId.contains("-")) { - id = UUID.fromString(bpmnId.replace("Step_", "")); - } - } catch (Exception ignored) {} - StepDto step = StepDto.builder() - .id(id) - .name(el.getAttribute("name")) - .build(); + StepDto step = StepDto.builder().name(el.getAttribute("name")).build(); if (bpmnType.contains("Event")) { step.setType(StepTypes.EVENT); @@ -252,10 +249,7 @@ public class BpmnService { if (shape.getAttribute("bpmnElement").equals(bpmnId)) { Element bounds = (Element) shape.getElementsByTagNameNS(DC_NS, "Bounds").item(0); if (bounds != null) { - step.setPosition(PositionDto.builder() - .x((int) Double.parseDouble(bounds.getAttribute("x"))) - .y((int) Double.parseDouble(bounds.getAttribute("y"))) - .build()); + step.setPosition(PositionDto.builder().x((int) Double.parseDouble(bounds.getAttribute("x"))).y((int) Double.parseDouble(bounds.getAttribute("y"))).width((int) Double.parseDouble(bounds.getAttribute("width"))).height((int) Double.parseDouble(bounds.getAttribute("height"))).build()); } break; } @@ -264,28 +258,18 @@ public class BpmnService { return step; } - private TransitionDto parseTransition(Element el, Map bpmnIdToStepId, Document doc) { + private TransitionDto parseTransition(Element el, Map bpmnIdToStep, Document doc) { + String bpmnId = el.getAttribute("id"); String sourceRef = el.getAttribute("sourceRef"); String targetRef = el.getAttribute("targetRef"); - if (!bpmnIdToStepId.containsKey(sourceRef) || !bpmnIdToStepId.containsKey(targetRef)) { + if (!bpmnIdToStep.containsKey(sourceRef) || !bpmnIdToStep.containsKey(targetRef)) { return null; } - UUID id = UUID.randomUUID(); - String bpmnId = el.getAttribute("id"); - try { - if (bpmnId.contains("-")) { - id = UUID.fromString(bpmnId.replace("Flow_", "")); - } - } catch (Exception ignored) {} + StepDto sourceStep = bpmnIdToStep.get(sourceRef); + StepDto targetStep = bpmnIdToStep.get(targetRef); - TransitionDto transition = TransitionDto.builder() - .id(id) - .name(el.getAttribute("name")) - .currentStepId(bpmnIdToStepId.get(sourceRef)) - .nextStepId(bpmnIdToStepId.get(targetRef)) - .waypoints(new ArrayList<>()) - .build(); + TransitionDto transition = TransitionDto.builder().name(el.getAttribute("name")).currentStepId(sourceStep.getId()).nextStepId(targetStep.getId()).actionName("DEFAULT").actionValue("DEFAULT").waypoints(new ArrayList<>()).build(); // Parse DI for waypoints NodeList edges = doc.getElementsByTagNameNS(BPMNDI_NS, "BPMNEdge"); @@ -293,14 +277,63 @@ public class BpmnService { Element edge = (Element) edges.item(i); if (edge.getAttribute("bpmnElement").equals(bpmnId)) { NodeList waypoints = edge.getElementsByTagNameNS(DI_NS, "waypoint"); - for (int j = 0; j < waypoints.getLength(); j++) { - Element wp = (Element) waypoints.item(j); - transition.getWaypoints().add(PositionDto.builder() - .x((int) Double.parseDouble(wp.getAttribute("x"))) - .y((int) Double.parseDouble(wp.getAttribute("y"))) - .build()); + + if (waypoints.getLength() > 0) { + Element sp = (Element) waypoints.item(0); + + int startX = Integer.parseInt(sp.getAttribute("x")); + int startY = Integer.parseInt(sp.getAttribute("y")); + + + Side side; + + if (startX == sourceStep.getPosition().getX()) { + side = Side.LEFT; + } else if (startX == sourceStep.getPosition().getX() + sourceStep.getPosition().getWidth()) { + side = Side.RIGHT; + } else if (startY == sourceStep.getPosition().getY()) { + side = Side.TOP; + } else if (startY == sourceStep.getPosition().getY() + sourceStep.getPosition().getHeight()) { + side = Side.BOTTOM; + } else { + side = Side.RIGHT; + } + + transition.setFromAnchor(AnchorDto.builder().side(side).sideIndex(2).build()); + + } + + if (waypoints.getLength() > 1) { + Element ep = (Element) waypoints.item(waypoints.getLength() - 1); + int startX = Integer.parseInt(ep.getAttribute("x")); + int startY = Integer.parseInt(ep.getAttribute("y")); + + + Side side; + + if (startX == targetStep.getPosition().getX()) { + side = Side.LEFT; + } else if (startX == targetStep.getPosition().getX() + targetStep.getPosition().getWidth()) { + side = Side.RIGHT; + } else if (startY == targetStep.getPosition().getY()) { + side = Side.TOP; + } else if (startY == targetStep.getPosition().getY() + targetStep.getPosition().getHeight()) { + side = Side.BOTTOM; + } else { + side = Side.LEFT; + } + + + transition.setToAnchor(AnchorDto.builder().side(side).sideIndex(2).build()); + + } + if (waypoints.getLength() > 2) { + for (int j = 1; j < waypoints.getLength() - 1; j++) { + Element wp = (Element) waypoints.item(j); + transition.getWaypoints().add(PositionDto.builder().x((int) Double.parseDouble(wp.getAttribute("x"))).y((int) Double.parseDouble(wp.getAttribute("y"))).build()); + } + break; } - break; } } diff --git a/src/main/java/xyz/pkay/veloflow/editor/service/StepEditorService.java b/src/main/java/xyz/pkay/veloflow/editor/service/StepEditorService.java index 9ec7fc7..1040d7c 100644 --- a/src/main/java/xyz/pkay/veloflow/editor/service/StepEditorService.java +++ b/src/main/java/xyz/pkay/veloflow/editor/service/StepEditorService.java @@ -63,7 +63,7 @@ public class StepEditorService { existingStep.setName(stepDto.getName()); existingStep.setType(stepDto.getType()); - existingStep.setOrder(stepDto.getOrder()); +// existingStep.setOrder(stepDto.getOrder()); existingStep.setPosition(mapper.toEntity(stepDto.getPosition())); existingStep.setEventType(stepDto.getEventType()); existingStep.setTaskSubType(stepDto.getTaskSubType()); diff --git a/src/test/java/xyz/pkay/veloflow/editor/service/BpmnServiceTest.java b/src/test/java/xyz/pkay/veloflow/editor/service/BpmnServiceTest.java index ec6ce84..c9997d4 100644 --- a/src/test/java/xyz/pkay/veloflow/editor/service/BpmnServiceTest.java +++ b/src/test/java/xyz/pkay/veloflow/editor/service/BpmnServiceTest.java @@ -80,4 +80,28 @@ public class BpmnServiceTest { assertEquals(importedStep2.getId(), importedTransition.getNextStepId()); assertEquals(2, importedTransition.getWaypoints().size()); } + + @Test + public void testImportWithBOM() throws Exception { + String bpmnXml = "\n" + + "\n" + + " \n" + + ""; + String xmlWithBOM = "\uFEFF" + bpmnXml; + + WorkflowDto importedWorkflow = bpmnService.importFromBpmn(xmlWithBOM); + assertEquals("Test Workflow BOM", importedWorkflow.getName()); + } + + @Test + public void testImportWithQuotedXml() throws Exception { + String bpmnXml = "\n" + + "\n" + + " \n" + + ""; + String quotedXml = "\"" + bpmnXml.replace("\"", "\\\"").replace("\n", "\\n") + "\""; + + WorkflowDto importedWorkflow = bpmnService.importFromBpmn(quotedXml); + assertEquals("Test Workflow", importedWorkflow.getName()); + } } -- GitLab From 02d34ddb999efc3307ac5d3573ebfa3bd03e96fc Mon Sep 17 00:00:00 2001 From: pratyush Date: Sat, 7 Mar 2026 22:48:43 +0000 Subject: [PATCH 3/3] Update anchor sideIndex values from 2 to 1 in `BpmnService` transition logic --- .../java/xyz/pkay/veloflow/editor/service/BpmnService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java b/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java index 9c8f606..ba7010d 100644 --- a/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java +++ b/src/main/java/xyz/pkay/veloflow/editor/service/BpmnService.java @@ -299,7 +299,7 @@ public class BpmnService { side = Side.RIGHT; } - transition.setFromAnchor(AnchorDto.builder().side(side).sideIndex(2).build()); + transition.setFromAnchor(AnchorDto.builder().side(side).sideIndex(1).build()); } @@ -324,7 +324,7 @@ public class BpmnService { } - transition.setToAnchor(AnchorDto.builder().side(side).sideIndex(2).build()); + transition.setToAnchor(AnchorDto.builder().side(side).sideIndex(1).build()); } if (waypoints.getLength() > 2) { -- GitLab