diff --git a/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/RegressionTest.java b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/RegressionTest.java index c7aa9a3..4d1b837 100644 --- a/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/RegressionTest.java +++ b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/RegressionTest.java @@ -137,6 +137,12 @@ public class RegressionTest { root.resolve("state_machines/maven_multi_module/core-module"), Path.of("src/test/resources/golden/MavenOrderStateMachine"), "MavenOrderStateMachine" + ), + new TestScenario( + "Complex Multi-Module Sample", + root.resolve("state_machines/complex_multi_module_sm"), + Path.of("src/test/resources/golden/StateMachineConfig"), + "StateMachineConfig" ) ); } diff --git a/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.dot b/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.dot new file mode 100644 index 0000000..d4c487b --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.dot @@ -0,0 +1,15 @@ +digraph statemachine { + rankdir=LR; + node [shape=rounded, style=filled, fillcolor=white, fontname="Arial"]; + edge [fontname="Arial", fontsize=10]; + + _start [shape=circle, label="", fillcolor=black, width=0.1]; + _start -> NEW; + COMPLETED [fillcolor=lightgray]; + CANCELLED [fillcolor=lightgray]; + NEW -> PROCESSING [label="OrderEvent.PROCESS", style="solid", color="black"]; + PROCESSING -> COMPLETED [label="OrderEvent.COMPLETE", style="solid", color="black"]; + NEW -> CANCELLED [label="OrderEvent.CANCEL", style="solid", color="black"]; + PROCESSING -> CANCELLED [label="OrderEvent.CANCEL", style="solid", color="black"]; +} + diff --git a/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.json b/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.json new file mode 100644 index 0000000..9ef51be --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.json @@ -0,0 +1,429 @@ +{ + "metadata" : { + "triggers" : [ { + "event" : "event", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendMessage", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 25 + }, { + "event" : "eventProvider", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendMessageWithProvider", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 50 + }, { + "event" : "customMessage", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendCustomMessage", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 78 + } ], + "entryPoints" : [ { + "type" : "REST", + "name" : "POST /api/orders/process", + "className" : "click.kamil.web.OrderController", + "methodName" : "processOrder", + "sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java", + "metadata" : { + "path" : "/api/orders/process", + "verb" : "POST" + }, + "parameters" : [ ] + }, { + "type" : "REST", + "name" : "POST /api/orders/complete", + "className" : "click.kamil.web.OrderController", + "methodName" : "completeOrder", + "sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java", + "metadata" : { + "path" : "/api/orders/complete", + "verb" : "POST" + }, + "parameters" : [ ] + }, { + "type" : "REST", + "name" : "POST /api/orders/cancel", + "className" : "click.kamil.web.OrderController", + "methodName" : "cancelOrder", + "sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java", + "metadata" : { + "path" : "/api/orders/cancel", + "verb" : "POST" + }, + "parameters" : [ ] + }, { + "type" : "REST", + "name" : "POST /api/orders/functional-complete", + "className" : "click.kamil.web.OrderController", + "methodName" : "functionalCompleteOrder", + "sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java", + "metadata" : { + "path" : "/api/orders/functional-complete", + "verb" : "POST" + }, + "parameters" : [ ] + }, { + "type" : "RABBIT", + "name" : "RABBIT: order.custom.transition.queue", + "className" : "click.kamil.web.RabbitOrderListener", + "methodName" : "handleCustomTransition", + "sourceFile" : "web/src/main/java/click/kamil/web/RabbitOrderListener.java", + "metadata" : { + "protocol" : "RABBIT", + "destination" : "order.custom.transition.queue" + }, + "parameters" : [ { + "name" : "payload", + "type" : "String", + "annotations" : [ ] + } ] + }, { + "type" : "JMS", + "name" : "JMS: order.process.queue", + "className" : "click.kamil.web.JmsOrderListener", + "methodName" : "receiveProcessCommand", + "sourceFile" : "web/src/main/java/click/kamil/web/JmsOrderListener.java", + "metadata" : { + "protocol" : "JMS", + "destination" : "order.process.queue" + }, + "parameters" : [ { + "name" : "message", + "type" : "String", + "annotations" : [ ] + } ] + }, { + "type" : "JMS", + "name" : "JMS: order.cancel.queue", + "className" : "click.kamil.web.JmsOrderListener", + "methodName" : "receiveCancelCommand", + "sourceFile" : "web/src/main/java/click/kamil/web/JmsOrderListener.java", + "metadata" : { + "protocol" : "JMS", + "destination" : "order.cancel.queue" + }, + "parameters" : [ { + "name" : "message", + "type" : "String", + "annotations" : [ ] + } ] + } ], + "callChains" : [ { + "entryPoint" : { + "type" : "REST", + "name" : "POST /api/orders/process", + "className" : "click.kamil.web.OrderController", + "methodName" : "processOrder", + "sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java", + "metadata" : { + "path" : "/api/orders/process", + "verb" : "POST" + }, + "parameters" : [ ] + }, + "methodChain" : [ "click.kamil.web.OrderController.processOrder", "click.kamil.service.StateMachineServiceImpl.sendMessageWithOutbox", "click.kamil.service.StateMachineServiceImpl.sendMessage" ], + "triggerPoint" : { + "event" : "OrderEvent.PROCESS", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendMessage", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 25 + }, + "contextMachineId" : null, + "matchedTransitions" : [ { + "sourceState" : "OrderState.NEW", + "targetState" : "OrderState.PROCESSING", + "event" : "OrderEvent.PROCESS" + } ] + }, { + "entryPoint" : { + "type" : "REST", + "name" : "POST /api/orders/complete", + "className" : "click.kamil.web.OrderController", + "methodName" : "completeOrder", + "sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java", + "metadata" : { + "path" : "/api/orders/complete", + "verb" : "POST" + }, + "parameters" : [ ] + }, + "methodChain" : [ "click.kamil.web.OrderController.completeOrder", "click.kamil.service.StateMachineServiceImpl.sendMessage" ], + "triggerPoint" : { + "event" : "OrderEvent.COMPLETE", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendMessage", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 25 + }, + "contextMachineId" : null, + "matchedTransitions" : [ { + "sourceState" : "OrderState.PROCESSING", + "targetState" : "OrderState.COMPLETED", + "event" : "OrderEvent.COMPLETE" + } ] + }, { + "entryPoint" : { + "type" : "REST", + "name" : "POST /api/orders/cancel", + "className" : "click.kamil.web.OrderController", + "methodName" : "cancelOrder", + "sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java", + "metadata" : { + "path" : "/api/orders/cancel", + "verb" : "POST" + }, + "parameters" : [ ] + }, + "methodChain" : [ "click.kamil.web.OrderController.cancelOrder", "click.kamil.service.StateMachineServiceImpl.sendMessage" ], + "triggerPoint" : { + "event" : "OrderEvent.CANCEL", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendMessage", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 25 + }, + "contextMachineId" : null, + "matchedTransitions" : [ { + "sourceState" : "OrderState.NEW", + "targetState" : "OrderState.CANCELLED", + "event" : "OrderEvent.CANCEL" + }, { + "sourceState" : "OrderState.PROCESSING", + "targetState" : "OrderState.CANCELLED", + "event" : "OrderEvent.CANCEL" + } ] + }, { + "entryPoint" : { + "type" : "REST", + "name" : "POST /api/orders/functional-complete", + "className" : "click.kamil.web.OrderController", + "methodName" : "functionalCompleteOrder", + "sourceFile" : "web/src/main/java/click/kamil/web/OrderController.java", + "metadata" : { + "path" : "/api/orders/functional-complete", + "verb" : "POST" + }, + "parameters" : [ ] + }, + "methodChain" : [ "click.kamil.web.OrderController.functionalCompleteOrder", "click.kamil.web.OrderController.triggerTransitionFunction", "click.kamil.service.StateMachineServiceImpl.sendMessage" ], + "triggerPoint" : { + "event" : "OrderEvent.COMPLETE", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendMessage", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 25 + }, + "contextMachineId" : null, + "matchedTransitions" : [ { + "sourceState" : "OrderState.PROCESSING", + "targetState" : "OrderState.COMPLETED", + "event" : "OrderEvent.COMPLETE" + } ] + }, { + "entryPoint" : { + "type" : "RABBIT", + "name" : "RABBIT: order.custom.transition.queue", + "className" : "click.kamil.web.RabbitOrderListener", + "methodName" : "handleCustomTransition", + "sourceFile" : "web/src/main/java/click/kamil/web/RabbitOrderListener.java", + "metadata" : { + "protocol" : "RABBIT", + "destination" : "order.custom.transition.queue" + }, + "parameters" : [ { + "name" : "payload", + "type" : "String", + "annotations" : [ ] + } ] + }, + "methodChain" : [ "click.kamil.web.RabbitOrderListener.handleCustomTransition", "click.kamil.service.StateMachineServiceImpl.sendCustomMessage" ], + "triggerPoint" : { + "event" : "OrderEvent.PROCESS", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendCustomMessage", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 78 + }, + "contextMachineId" : null, + "matchedTransitions" : [ { + "sourceState" : "OrderState.NEW", + "targetState" : "OrderState.PROCESSING", + "event" : "OrderEvent.PROCESS" + } ] + }, { + "entryPoint" : { + "type" : "JMS", + "name" : "JMS: order.process.queue", + "className" : "click.kamil.web.JmsOrderListener", + "methodName" : "receiveProcessCommand", + "sourceFile" : "web/src/main/java/click/kamil/web/JmsOrderListener.java", + "metadata" : { + "protocol" : "JMS", + "destination" : "order.process.queue" + }, + "parameters" : [ { + "name" : "message", + "type" : "String", + "annotations" : [ ] + } ] + }, + "methodChain" : [ "click.kamil.web.JmsOrderListener.receiveProcessCommand", "click.kamil.service.StateMachineServiceImpl.sendMessageWithOutbox", "click.kamil.service.StateMachineServiceImpl.sendMessage" ], + "triggerPoint" : { + "event" : "OrderEvent.PROCESS", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendMessage", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 25 + }, + "contextMachineId" : null, + "matchedTransitions" : [ { + "sourceState" : "OrderState.NEW", + "targetState" : "OrderState.PROCESSING", + "event" : "OrderEvent.PROCESS" + } ] + }, { + "entryPoint" : { + "type" : "JMS", + "name" : "JMS: order.cancel.queue", + "className" : "click.kamil.web.JmsOrderListener", + "methodName" : "receiveCancelCommand", + "sourceFile" : "web/src/main/java/click/kamil/web/JmsOrderListener.java", + "metadata" : { + "protocol" : "JMS", + "destination" : "order.cancel.queue" + }, + "parameters" : [ { + "name" : "message", + "type" : "String", + "annotations" : [ ] + } ] + }, + "methodChain" : [ "click.kamil.web.JmsOrderListener.receiveCancelCommand", "click.kamil.service.StateMachineServiceImpl.sendMessageWithProvider" ], + "triggerPoint" : { + "event" : "OrderEvent.CANCEL", + "className" : "click.kamil.service.StateMachineServiceImpl", + "methodName" : "sendMessageWithProvider", + "sourceFile" : "service/src/main/java/click/kamil/service/StateMachineServiceImpl.java", + "sourceModule" : null, + "stateMachineId" : null, + "sourceState" : null, + "lineNumber" : 50 + }, + "contextMachineId" : null, + "matchedTransitions" : [ { + "sourceState" : "OrderState.NEW", + "targetState" : "OrderState.CANCELLED", + "event" : "OrderEvent.CANCEL" + }, { + "sourceState" : "OrderState.PROCESSING", + "targetState" : "OrderState.CANCELLED", + "event" : "OrderEvent.CANCEL" + } ] + } ], + "properties" : { + "default" : { } + } + }, + "name" : "click.kamil.domain.StateMachineConfig", + "renderChoicesAsDiamonds" : true, + "startStates" : [ "OrderState.NEW" ], + "transitions" : [ { + "type" : "EXTERNAL", + "sourceStates" : [ { + "rawName" : "OrderState.NEW", + "fullIdentifier" : "OrderState.NEW" + } ], + "targetStates" : [ { + "rawName" : "OrderState.PROCESSING", + "fullIdentifier" : "OrderState.PROCESSING" + } ], + "event" : { + "rawName" : "OrderEvent.PROCESS", + "fullIdentifier" : "OrderEvent.PROCESS" + }, + "guard" : null, + "actions" : [ ], + "order" : null + }, { + "type" : "EXTERNAL", + "sourceStates" : [ { + "rawName" : "OrderState.PROCESSING", + "fullIdentifier" : "OrderState.PROCESSING" + } ], + "targetStates" : [ { + "rawName" : "OrderState.COMPLETED", + "fullIdentifier" : "OrderState.COMPLETED" + } ], + "event" : { + "rawName" : "OrderEvent.COMPLETE", + "fullIdentifier" : "OrderEvent.COMPLETE" + }, + "guard" : null, + "actions" : [ ], + "order" : null + }, { + "type" : "EXTERNAL", + "sourceStates" : [ { + "rawName" : "OrderState.NEW", + "fullIdentifier" : "OrderState.NEW" + } ], + "targetStates" : [ { + "rawName" : "OrderState.CANCELLED", + "fullIdentifier" : "OrderState.CANCELLED" + } ], + "event" : { + "rawName" : "OrderEvent.CANCEL", + "fullIdentifier" : "OrderEvent.CANCEL" + }, + "guard" : null, + "actions" : [ ], + "order" : null + }, { + "type" : "EXTERNAL", + "sourceStates" : [ { + "rawName" : "OrderState.PROCESSING", + "fullIdentifier" : "OrderState.PROCESSING" + } ], + "targetStates" : [ { + "rawName" : "OrderState.CANCELLED", + "fullIdentifier" : "OrderState.CANCELLED" + } ], + "event" : { + "rawName" : "OrderEvent.CANCEL", + "fullIdentifier" : "OrderEvent.CANCEL" + }, + "guard" : null, + "actions" : [ ], + "order" : null + } ], + "endStates" : [ "OrderState.COMPLETED", "OrderState.CANCELLED" ] +} diff --git a/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.puml b/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.puml new file mode 100644 index 0000000..c9cfecb --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.puml @@ -0,0 +1,35 @@ +@startuml +!pragma layout smetana +set separator none +hide empty description +hide stereotype +skinparam state { + BackgroundColor white + BorderColor #94a3b8 + BorderThickness 1 + FontName Inter + FontSize 9 + FontStyle bold + RoundCorner 20 + Padding 1 +} +skinparam shadowing false +skinparam ArrowFontName JetBrains Mono +skinparam ArrowFontSize 8 +skinparam ArrowColor #cbd5e1 +skinparam ArrowThickness 1 +skinparam dpi 110 +skinparam svgLinkTarget _self + +[*] --> OrderState.NEW + + +OrderState.NEW -[#1E90FF,bold]-> OrderState.PROCESSING <> : OrderEvent.PROCESS +OrderState.PROCESSING -[#1E90FF,bold]-> OrderState.COMPLETED <> : OrderEvent.COMPLETE +OrderState.NEW -[#1E90FF,bold]-> OrderState.CANCELLED <> : OrderEvent.CANCEL +OrderState.PROCESSING -[#1E90FF,bold]-> OrderState.CANCELLED <> : OrderEvent.CANCEL + +OrderState.COMPLETED --> [*] +OrderState.CANCELLED --> [*] +@enduml + diff --git a/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.scxml.xml b/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.scxml.xml new file mode 100644 index 0000000..c661eba --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/StateMachineConfig/StateMachineConfig.scxml.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + +