diff --git a/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/ast/common/CodebaseContextTest.java b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/ast/common/CodebaseContextTest.java new file mode 100644 index 0000000..d94a042 --- /dev/null +++ b/state_machine_exporter/src/test/java/click/kamil/springstatemachineexporter/ast/common/CodebaseContextTest.java @@ -0,0 +1,100 @@ +package click.kamil.springstatemachineexporter.ast.common; + +import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class CodebaseContextTest { + + @TempDir + Path tempDir; + + @Test + void shouldFindEntryPointByAnnotation() throws IOException { + String source = """ + package com.example; + import org.springframework.statemachine.config.EnableStateMachine; + @EnableStateMachine + public class MyConfig {} + """; + Files.writeString(tempDir.resolve("MyConfig.java"), source); + + CodebaseContext context = new CodebaseContext(); + context.scan(tempDir); + + List entryPoints = context.findEntryPointClasses(List.of("EnableStateMachine")); + assertThat(entryPoints).hasSize(1); + assertThat(entryPoints.get(0).getName().getIdentifier()).isEqualTo("MyConfig"); + } + + @Test + void shouldFindEntryPointByInheritance() throws IOException { + String baseSource = """ + package com.example; + import org.springframework.statemachine.config.StateMachineConfigurerAdapter; + public abstract class BaseConfig extends StateMachineConfigurerAdapter {} + """; + String leafSource = """ + package com.example; + public class LeafConfig extends BaseConfig {} + """; + Files.writeString(tempDir.resolve("BaseConfig.java"), baseSource); + Files.writeString(tempDir.resolve("LeafConfig.java"), leafSource); + + CodebaseContext context = new CodebaseContext(); + context.scan(tempDir); + + List entryPoints = context.findEntryPointClasses(List.of("EnableStateMachine")); + assertThat(entryPoints).hasSize(1); + assertThat(entryPoints.get(0).getName().getIdentifier()).isEqualTo("LeafConfig"); + } + + @Test + void shouldNotFindAbstractClassAsEntryPoint() throws IOException { + String source = """ + package com.example; + import org.springframework.statemachine.config.StateMachineConfigurerAdapter; + public abstract class MyConfig extends StateMachineConfigurerAdapter {} + """; + Files.writeString(tempDir.resolve("MyConfig.java"), source); + + CodebaseContext context = new CodebaseContext(); + context.scan(tempDir); + + List entryPoints = context.findEntryPointClasses(List.of("EnableStateMachine")); + assertThat(entryPoints).isEmpty(); + } + + @Test + void shouldResolveInheritanceWithImports() throws IOException { + Files.createDirectories(tempDir.resolve("base")); + Files.createDirectories(tempDir.resolve("leaf")); + + String baseSource = """ + package com.example.base; + import org.springframework.statemachine.config.StateMachineConfigurerAdapter; + public abstract class BaseConfig extends StateMachineConfigurerAdapter {} + """; + String leafSource = """ + package com.example.leaf; + import com.example.base.BaseConfig; + public class LeafConfig extends BaseConfig {} + """; + Files.writeString(tempDir.resolve("base/BaseConfig.java"), baseSource); + Files.writeString(tempDir.resolve("leaf/LeafConfig.java"), leafSource); + + CodebaseContext context = new CodebaseContext(); + context.scan(tempDir); + + List entryPoints = context.findEntryPointClasses(List.of("EnableStateMachine")); + assertThat(entryPoints).hasSize(1); + assertThat(entryPoints.get(0).getName().getIdentifier()).isEqualTo("LeafConfig"); + } +} diff --git a/state_machine_exporter/src/test/resources/golden/F1StateMachineConfiguration/F1StateMachineConfiguration.puml b/state_machine_exporter/src/test/resources/golden/F1StateMachineConfiguration/F1StateMachineConfiguration.puml new file mode 100644 index 0000000..05d40d7 --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/F1StateMachineConfiguration/F1StateMachineConfiguration.puml @@ -0,0 +1,76 @@ +@startuml +skinparam state { + BackgroundColor<> LightYellow +} + +[*] --> STATE1 + +state STATE17 <> +state STATE16 <> +state STATE2 <> +state STATE14 <> +state STATE12 <> +state STATE11 <> +state STATE8 <> +state STATEY <> +state STATE20 <> +state STATE9 <> +state STATE19 <> +state STATE18 <> + +STATE1 -[#1E90FF,bold]-> STATE2 : EVENT1 +STATE2 -[#1E90FF,bold]-> STATE3 : EVENT2 +STATE3 -[#1E90FF,bold]-> STATE4 : EVENT3 +STATE4 -[#1E90FF,bold]-> STATE5 : EVENT4 +STATE5 -[#1E90FF,bold]-> STATE6 : EVENT5 +STATE6 -[#1E90FF,bold]-> STATE7 : EVENT6 +STATE7 -[#1E90FF,bold]-> STATE8 : EVENT7 +STATE8 -[#1E90FF,bold]-> STATE9 : EVENT8 +STATE9 -[#1E90FF,bold]-> STATE10 : EVENT9 +STATE10 -[#1E90FF,bold]-> STATE11 : EVENT10 +STATE11 -[#1E90FF,bold]-> STATE12 : EVENT11 +STATE12 -[#1E90FF,bold]-> STATE13 : EVENT12 +STATE13 -[#1E90FF,bold]-> STATE14 : EVENT13 +STATE14 -[#1E90FF,bold]-> STATE15 : EVENT14 +STATE15 -[#1E90FF,bold]-> STATE16 : EVENT15 +STATE1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE3 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE5 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> STATEY : EVENTY +STATEY -[#4682B4,bold]-> STATEX : [guardVarEquals("value1")] (order=0) +STATEY -[#4682B4,bold]-> STATEZ : (order=1) +STATE16 -[#4682B4,bold]-> STATE17 : [guardVarEquals("value1")] (order=0) +STATE16 -[#4682B4,bold]-> STATE18 : [guardVarEquals("value2")] (order=1) +STATE16 -[#4682B4,bold]-> STATE19 : (order=2) +STATE17 -[#FF6347,bold]-> STATE20 : [guardEventHeaderEquals("header1","foo")] (order=0) +STATE17 -[#FF6347,bold]-> STATE16 : (order=1) +STATE18 -[#FF69B4,bold]-> STATE19 : [guardVarEquals("value3")] (order=0) +STATE18 -[#FF69B4,bold]-> STATE20 : (order=1) +STATE19 -[#6A5ACD,bold]-> STATE1 : [guardVarEquals("reset")] (order=0) +STATE19 -[#6A5ACD,bold]-> STATE20 : (order=1) +STATE20 -[#32CD32,bold]-> STATE5 : [guardEventHeaderEquals("header2","bar")] (order=0) +STATE20 -[#32CD32,bold]-> STATE1 : (order=1) +STATE11 -[#FF69B4,bold]-> STATE13 : [guardVarEquals("goTo13")] (order=0) +STATE11 -[#FF69B4,bold]-> STATE14 : [guardVarEquals("goTo14")] (order=1) +STATE11 -[#FF69B4,bold]-> STATE15 : (order=2) +STATE12 -[#6A5ACD,bold]-> STATE10 : [guardVarEquals("goBack10")] (order=0) +STATE12 -[#6A5ACD,bold]-> STATE11 : (order=1) +STATE14 -[#FFD700,bold]-> STATE12 : [guardVarEquals("loop12")] (order=0) +STATE14 -[#FFD700,bold]-> STATE16 : (order=1) +STATE9 -[#FFD700,bold]-> STATE8 : [guardVarEquals("stepBack")] (order=0) +STATE9 -[#FFD700,bold]-> STATE7 : [guardVarEquals("stepBackMore")] (order=1) +STATE9 -[#FFD700,bold]-> STATE6 : (order=2) +STATE8 -[#FF6347,bold]-> STATE9 : [guardVarEquals("forward9")] (order=0) +STATE8 -[#FF6347,bold]-> STATE10 : (order=1) +STATE2 -[#1E90FF,bold]-> STATE_EXTRA_1 : EVENTX +STATE2 -[#32CD32,bold]-> STATE1 : [guardEventHeaderEquals("header1","foo")] (order=0) +STATE2 -[#32CD32,bold]-> STATE_EXTRA_1 : (order=1) +STATE_EXTRA_1 -[#1E90FF,bold]-> STATE_EXTRA_3 : EVENTY +STATE_EXTRA_1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL_2 +STATE_EXTRA_2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL_2 + +STATEZ --> [*] +@enduml + diff --git a/state_machine_exporter/src/test/resources/golden/F2StateMachineConfiguration/F2StateMachineConfiguration.puml b/state_machine_exporter/src/test/resources/golden/F2StateMachineConfiguration/F2StateMachineConfiguration.puml new file mode 100644 index 0000000..6687e17 --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/F2StateMachineConfiguration/F2StateMachineConfiguration.puml @@ -0,0 +1,77 @@ +@startuml +skinparam state { + BackgroundColor<> LightYellow +} + +[*] --> STATE1 + +state STATE17 <> +state STATE16 <> +state STATE14 <> +state STATE12 <> +state STATE11 <> +state STATE8 <> +state STATEY <> +state STATE20 <> +state STATE9 <> +state STATE_EXTRA_1_2 <> +state STATE19 <> +state STATE18 <> + +STATE1 -[#1E90FF,bold]-> STATE2 : EVENT1 +STATE2 -[#1E90FF,bold]-> STATE3 : EVENT2 +STATE3 -[#1E90FF,bold]-> STATE4 : EVENT3 +STATE4 -[#1E90FF,bold]-> STATE5 : EVENT4 +STATE5 -[#1E90FF,bold]-> STATE6 : EVENT5 +STATE6 -[#1E90FF,bold]-> STATE7 : EVENT6 +STATE7 -[#1E90FF,bold]-> STATE8 : EVENT7 +STATE8 -[#1E90FF,bold]-> STATE9 : EVENT8 +STATE9 -[#1E90FF,bold]-> STATE10 : EVENT9 +STATE10 -[#1E90FF,bold]-> STATE11 : EVENT10 +STATE11 -[#1E90FF,bold]-> STATE12 : EVENT11 +STATE12 -[#1E90FF,bold]-> STATE13 : EVENT12 +STATE13 -[#1E90FF,bold]-> STATE14 : EVENT13 +STATE14 -[#1E90FF,bold]-> STATE15 : EVENT14 +STATE15 -[#1E90FF,bold]-> STATE16 : EVENT15 +STATE1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE3 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE5 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> STATEY : EVENTY +STATEY -[#FF6347,bold]-> STATEX : [guardVarEquals("value1")] (order=0) +STATEY -[#FF6347,bold]-> STATEZ : (order=1) +STATE16 -[#4682B4,bold]-> STATE17 : [guardVarEquals("value1")] (order=0) +STATE16 -[#4682B4,bold]-> STATE18 : [guardVarEquals("value2")] (order=1) +STATE16 -[#4682B4,bold]-> STATE19 : (order=2) +STATE17 -[#FF6347,bold]-> STATE20 : [guardEventHeaderEquals("header1","foo")] (order=0) +STATE17 -[#FF6347,bold]-> STATE16 : (order=1) +STATE18 -[#FF69B4,bold]-> STATE19 : [guardVarEquals("value3")] (order=0) +STATE18 -[#FF69B4,bold]-> STATE20 : (order=1) +STATE19 -[#6A5ACD,bold]-> STATE1 : [guardVarEquals("reset")] (order=0) +STATE19 -[#6A5ACD,bold]-> STATE20 : (order=1) +STATE20 -[#4682B4,bold]-> STATE5 : [guardEventHeaderEquals("header2","bar")] (order=0) +STATE20 -[#4682B4,bold]-> STATE1 : (order=1) +STATE11 -[#6A5ACD,bold]-> STATE13 : [guardVarEquals("goTo13")] (order=0) +STATE11 -[#6A5ACD,bold]-> STATE14 : [guardVarEquals("goTo14")] (order=1) +STATE11 -[#6A5ACD,bold]-> STATE15 : (order=2) +STATE12 -[#FFD700,bold]-> STATE10 : [guardVarEquals("goBack10")] (order=0) +STATE12 -[#FFD700,bold]-> STATE11 : (order=1) +STATE14 -[#32CD32,bold]-> STATE12 : [guardVarEquals("loop12")] (order=0) +STATE14 -[#32CD32,bold]-> STATE16 : (order=1) +STATE9 -[#32CD32,bold]-> STATE8 : [guardVarEquals("stepBack")] (order=0) +STATE9 -[#32CD32,bold]-> STATE7 : [guardVarEquals("stepBackMore")] (order=1) +STATE9 -[#32CD32,bold]-> STATE6 : (order=2) +STATE8 -[#FF69B4,bold]-> STATE9 : [guardVarEquals("forward9")] (order=0) +STATE8 -[#FF69B4,bold]-> STATE10 : (order=1) +STATE9 -[#1E90FF,bold]-> STATE_EXTRA_1_1 : EVENT_1_1 +STATE_EXTRA_1_2 -[#FFD700,bold]-> STATE_EXTRA_1_1 : [guardEventHeaderEquals("header1","foo")] (order=0) +STATE_EXTRA_1_2 -[#FFD700,bold]-> STATE_EXTRA_1_3 : (order=1) +STATE_EXTRA_1_3 -[#1E90FF,bold]-> STATE_EXTRA_1 : EVENT_1_2 +STATE_EXTRA_1_1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL_2 +STATE_EXTRA_1_2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL_2 +STATE_EXTRA_1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL_2 + +STATEZ --> [*] +@enduml + diff --git a/state_machine_exporter/src/test/resources/golden/G1StateMachineConfiguration/G1StateMachineConfiguration.puml b/state_machine_exporter/src/test/resources/golden/G1StateMachineConfiguration/G1StateMachineConfiguration.puml new file mode 100644 index 0000000..c546d51 --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/G1StateMachineConfiguration/G1StateMachineConfiguration.puml @@ -0,0 +1,40 @@ +@startuml +skinparam state { + BackgroundColor<> LightYellow +} + +[*] --> STATE1 + +state STATE8 <> +state STATEY <> +state STATE9 <> + +STATE1 -[#1E90FF,bold]-> STATE2 : EVENT1 +STATE2 -[#1E90FF,bold]-> STATE3 : EVENT2 +STATE3 -[#1E90FF,bold]-> STATE4 : EVENT3 +STATE4 -[#1E90FF,bold]-> STATE5 : EVENT4 +STATE5 -[#1E90FF,bold]-> STATE6 : EVENT5 +STATE6 -[#1E90FF,bold]-> STATE7 : EVENT6 +STATE7 -[#1E90FF,bold]-> STATE8 : EVENT7 +STATE8 -[#1E90FF,bold]-> STATE9 : EVENT8 +STATE9 -[#1E90FF,bold]-> STATE10 : EVENT9 +STATE1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE3 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE5 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> STATEY : EVENTY +STATEY -[#4682B4,bold]-> STATEX : [guardVarEquals("value1")] (order=0) +STATEY -[#4682B4,bold]-> STATEZ : (order=1) +STATE9 -[#32CD32,bold]-> STATE8 : [guardVarEquals("stepBack")] (order=0) +STATE9 -[#32CD32,bold]-> STATE7 : [guardVarEquals("stepBackMore")] (order=1) +STATE9 -[#32CD32,bold]-> STATE6 : (order=2) +STATE8 -[#FF6347,bold]-> STATE9 : [guardVarEquals("forward9")] (order=0) +STATE8 -[#FF6347,bold]-> STATE10 : (order=1) +STATE3 -[#1E90FF,bold]-> STATE_EXTRA_2 : EVENT_1_2 +STATE_EXTRA_2 -[#1E90FF,bold]-> STATE_EXTRA_3 : EVENT_1_2 +STATE_EXTRA_3 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL + +STATEZ --> [*] +@enduml + diff --git a/state_machine_exporter/src/test/resources/golden/G2StateMachineConfiguration/G2StateMachineConfiguration.puml b/state_machine_exporter/src/test/resources/golden/G2StateMachineConfiguration/G2StateMachineConfiguration.puml new file mode 100644 index 0000000..01cd684 --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/G2StateMachineConfiguration/G2StateMachineConfiguration.puml @@ -0,0 +1,41 @@ +@startuml +skinparam state { + BackgroundColor<> LightYellow +} + +[*] --> STATE1 + +state STATE8 <> +state STATEY <> +state STATE9 <> + +STATE1 -[#1E90FF,bold]-> STATE2 : EVENT1 +STATE2 -[#1E90FF,bold]-> STATE3 : EVENT2 +STATE3 -[#1E90FF,bold]-> STATE4 : EVENT3 +STATE4 -[#1E90FF,bold]-> STATE5 : EVENT4 +STATE5 -[#1E90FF,bold]-> STATE6 : EVENT5 +STATE6 -[#1E90FF,bold]-> STATE7 : EVENT6 +STATE7 -[#1E90FF,bold]-> STATE8 : EVENT7 +STATE8 -[#1E90FF,bold]-> STATE9 : EVENT8 +STATE9 -[#1E90FF,bold]-> STATE10 : EVENT9 +STATE1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE3 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE5 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> STATEY : EVENTY +STATEY -[#4682B4,bold]-> STATEX : [guardVarEquals("value1")] (order=0) +STATEY -[#4682B4,bold]-> STATEZ : (order=1) +STATE9 -[#32CD32,bold]-> STATE8 : [guardVarEquals("stepBack")] (order=0) +STATE9 -[#32CD32,bold]-> STATE7 : [guardVarEquals("stepBackMore")] (order=1) +STATE9 -[#32CD32,bold]-> STATE6 : (order=2) +STATE8 -[#FF6347,bold]-> STATE9 : [guardVarEquals("forward9")] (order=0) +STATE8 -[#FF6347,bold]-> STATE10 : (order=1) +STATE3 -[#1E90FF,bold]-> STATE_EXTRA_1 : EVENT_1_2 +STATE_EXTRA_1 -[#1E90FF,bold]-> STATE_EXTRA_2 : EVENT_1_3 +STATE_EXTRA_1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE_EXTRA_2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL + +STATEZ --> [*] +@enduml + diff --git a/state_machine_exporter/src/test/resources/golden/ThreeStateMachineConfiguration/ThreeStateMachineConfiguration.puml b/state_machine_exporter/src/test/resources/golden/ThreeStateMachineConfiguration/ThreeStateMachineConfiguration.puml new file mode 100644 index 0000000..05d40d7 --- /dev/null +++ b/state_machine_exporter/src/test/resources/golden/ThreeStateMachineConfiguration/ThreeStateMachineConfiguration.puml @@ -0,0 +1,76 @@ +@startuml +skinparam state { + BackgroundColor<> LightYellow +} + +[*] --> STATE1 + +state STATE17 <> +state STATE16 <> +state STATE2 <> +state STATE14 <> +state STATE12 <> +state STATE11 <> +state STATE8 <> +state STATEY <> +state STATE20 <> +state STATE9 <> +state STATE19 <> +state STATE18 <> + +STATE1 -[#1E90FF,bold]-> STATE2 : EVENT1 +STATE2 -[#1E90FF,bold]-> STATE3 : EVENT2 +STATE3 -[#1E90FF,bold]-> STATE4 : EVENT3 +STATE4 -[#1E90FF,bold]-> STATE5 : EVENT4 +STATE5 -[#1E90FF,bold]-> STATE6 : EVENT5 +STATE6 -[#1E90FF,bold]-> STATE7 : EVENT6 +STATE7 -[#1E90FF,bold]-> STATE8 : EVENT7 +STATE8 -[#1E90FF,bold]-> STATE9 : EVENT8 +STATE9 -[#1E90FF,bold]-> STATE10 : EVENT9 +STATE10 -[#1E90FF,bold]-> STATE11 : EVENT10 +STATE11 -[#1E90FF,bold]-> STATE12 : EVENT11 +STATE12 -[#1E90FF,bold]-> STATE13 : EVENT12 +STATE13 -[#1E90FF,bold]-> STATE14 : EVENT13 +STATE14 -[#1E90FF,bold]-> STATE15 : EVENT14 +STATE15 -[#1E90FF,bold]-> STATE16 : EVENT15 +STATE1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE3 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE5 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL +STATE4 -[#1E90FF,bold]-> STATEY : EVENTY +STATEY -[#4682B4,bold]-> STATEX : [guardVarEquals("value1")] (order=0) +STATEY -[#4682B4,bold]-> STATEZ : (order=1) +STATE16 -[#4682B4,bold]-> STATE17 : [guardVarEquals("value1")] (order=0) +STATE16 -[#4682B4,bold]-> STATE18 : [guardVarEquals("value2")] (order=1) +STATE16 -[#4682B4,bold]-> STATE19 : (order=2) +STATE17 -[#FF6347,bold]-> STATE20 : [guardEventHeaderEquals("header1","foo")] (order=0) +STATE17 -[#FF6347,bold]-> STATE16 : (order=1) +STATE18 -[#FF69B4,bold]-> STATE19 : [guardVarEquals("value3")] (order=0) +STATE18 -[#FF69B4,bold]-> STATE20 : (order=1) +STATE19 -[#6A5ACD,bold]-> STATE1 : [guardVarEquals("reset")] (order=0) +STATE19 -[#6A5ACD,bold]-> STATE20 : (order=1) +STATE20 -[#32CD32,bold]-> STATE5 : [guardEventHeaderEquals("header2","bar")] (order=0) +STATE20 -[#32CD32,bold]-> STATE1 : (order=1) +STATE11 -[#FF69B4,bold]-> STATE13 : [guardVarEquals("goTo13")] (order=0) +STATE11 -[#FF69B4,bold]-> STATE14 : [guardVarEquals("goTo14")] (order=1) +STATE11 -[#FF69B4,bold]-> STATE15 : (order=2) +STATE12 -[#6A5ACD,bold]-> STATE10 : [guardVarEquals("goBack10")] (order=0) +STATE12 -[#6A5ACD,bold]-> STATE11 : (order=1) +STATE14 -[#FFD700,bold]-> STATE12 : [guardVarEquals("loop12")] (order=0) +STATE14 -[#FFD700,bold]-> STATE16 : (order=1) +STATE9 -[#FFD700,bold]-> STATE8 : [guardVarEquals("stepBack")] (order=0) +STATE9 -[#FFD700,bold]-> STATE7 : [guardVarEquals("stepBackMore")] (order=1) +STATE9 -[#FFD700,bold]-> STATE6 : (order=2) +STATE8 -[#FF6347,bold]-> STATE9 : [guardVarEquals("forward9")] (order=0) +STATE8 -[#FF6347,bold]-> STATE10 : (order=1) +STATE2 -[#1E90FF,bold]-> STATE_EXTRA_1 : EVENTX +STATE2 -[#32CD32,bold]-> STATE1 : [guardEventHeaderEquals("header1","foo")] (order=0) +STATE2 -[#32CD32,bold]-> STATE_EXTRA_1 : (order=1) +STATE_EXTRA_1 -[#1E90FF,bold]-> STATE_EXTRA_3 : EVENTY +STATE_EXTRA_1 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL_2 +STATE_EXTRA_2 -[#1E90FF,bold]-> CANCEL : EVENT_CANCEL_2 + +STATEZ --> [*] +@enduml + diff --git a/state_machines/inheritance_extra_functions3_state_machine/.gitignore b/state_machines/inheritance_extra_functions3_state_machine/.gitignore new file mode 100644 index 0000000..c022c2a --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/.gitignore @@ -0,0 +1,45 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + + + +#### added +*.png +*.dot +*.scxml.xml +Combined.java \ No newline at end of file diff --git a/state_machines/inheritance_extra_functions3_state_machine/build.gradle b/state_machines/inheritance_extra_functions3_state_machine/build.gradle new file mode 100644 index 0000000..0f14971 --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/build.gradle @@ -0,0 +1,42 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.5.3' + id 'io.spring.dependency-management' version '1.1.7' +} + +group = 'click.kamil' +version = '0.0.1-SNAPSHOT' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +repositories { + mavenCentral() +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.statemachine:spring-statemachine-starter:3.2.0' + + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/AbstractFStateMachineConfiguration.java b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/AbstractFStateMachineConfiguration.java new file mode 100644 index 0000000..1224fcc --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/AbstractFStateMachineConfiguration.java @@ -0,0 +1,203 @@ +package click.kamil.examples.statemachine.inheritanceextrafunctionsstate3; + +import org.springframework.statemachine.action.Action; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.config.configurers.ExternalTransitionConfigurer; +import org.springframework.statemachine.config.configurers.StateConfigurer; +import org.springframework.statemachine.guard.Guard; + +abstract class AbstractFStateMachineConfiguration extends AbstractStateMachineConfiguration { + + protected abstract void addAdditionalStates(StateConfigurer states); + + protected abstract void addAdditionalCancellationTransitions(StateMachineTransitionConfigurer transitions); + + protected abstract void addAdditionalTransitions(ExternalTransitionConfigurer transitions) throws Exception; + + protected void addAllCancellationTransitionsForSource(StateMachineTransitionConfigurer transitions, States source) { + addCancellationTransitionForCancelEvents(transitions, source, Events.EVENT_CANCEL_2); + } + + private void addCancellationTransitionForCancelEvents( + StateMachineTransitionConfigurer transitions, + States source, + Events... cancelEvents) { + addTransitionForMultipleEvents( + transitions, + source, + States.CANCEL, + transitionConfigurer -> transitionConfigurer.action((context) -> System.out.println(context.getEvent().toString() + " " + context.getTransition().toString())), + cancelEvents + ); + } + + @Override + public void configure(StateMachineConfigurationConfigurer config) throws Exception { + config + .withConfiguration() + .autoStartup(true); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + StateConfigurer end = states + .withStates() + .initial(States.STATE1) + .state(States.STATE2) + .state(States.STATE3) + .state(States.STATE4) + .state(States.STATE5) + .state(States.STATE6) + .state(States.STATE7) + .state(States.STATE8) + .state(States.STATE9) + .state(States.STATE10) + .state(States.STATE11) + .state(States.STATE12) + .state(States.STATE13) + .state(States.STATE14) + .state(States.STATE15) + .state(States.STATE16) + .state(States.STATE17) + .state(States.STATE18) + .state(States.STATE19) + .state(States.STATE20) + .state(States.STATEX) + .choice(States.STATEY) + .end(States.STATEZ); + addAdditionalStates(end); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + + // External transitions + ExternalTransitionConfigurer t1 = transitions + .withExternal().source(States.STATE1).target(States.STATE2).event(Events.EVENT1) + .and() + .withExternal().source(States.STATE2).target(States.STATE3).event(Events.EVENT2) + .and() + .withExternal().source(States.STATE3).target(States.STATE4).event(Events.EVENT3) + .and() + .withExternal().source(States.STATE4).target(States.STATE5).event(Events.EVENT4) + .and() + .withExternal().source(States.STATE5).target(States.STATE6).event(Events.EVENT5) + .and() + .withExternal().source(States.STATE6).target(States.STATE7).event(Events.EVENT6) + .and() + .withExternal().source(States.STATE7).target(States.STATE8).event(Events.EVENT7) + .and() + .withExternal().source(States.STATE8).target(States.STATE9).event(Events.EVENT8) + .and() + .withExternal().source(States.STATE9).target(States.STATE10).event(Events.EVENT9) + .and() + .withExternal().source(States.STATE10).target(States.STATE11).event(Events.EVENT10) + .and() + .withExternal().source(States.STATE11).target(States.STATE12).event(Events.EVENT11) + .and() + .withExternal().source(States.STATE12).target(States.STATE13).event(Events.EVENT12) + .and() + .withExternal().source(States.STATE13).target(States.STATE14).event(Events.EVENT13) + .and() + .withExternal().source(States.STATE14).target(States.STATE15).event(Events.EVENT14) + .and() + .withExternal().source(States.STATE15).target(States.STATE16).event(Events.EVENT15); + + transitions.withExternal().source(States.STATE1).target(States.CANCEL).event(Events.EVENT_CANCEL) + .and() + .withExternal().source(States.STATE2).target(States.CANCEL).event(Events.EVENT_CANCEL) + .and() + .withExternal().source(States.STATE3).target(States.CANCEL).event(Events.EVENT_CANCEL) + .and() + .withExternal().source(States.STATE4).target(States.CANCEL).event(Events.EVENT_CANCEL) + .and() + .withExternal().source(States.STATE5).target(States.CANCEL).event(Events.EVENT_CANCEL); + + // EXTRA CHOICE + transitions.withExternal().source(States.STATE4).target(States.STATEY).event(Events.EVENTY); + transitions.withChoice().source(States.STATEY).first(States.STATEX, guardVarEquals("value1")).last(States.STATEZ); + + // Choice transitions (at least 10) + transitions + .withChoice() + .source(States.STATE16) + .first(States.STATE17, guardVarEquals("value1")) + .then(States.STATE18, guardVarEquals("value2")) + .last(States.STATE19) + .and() + .withChoice() + .source(States.STATE17) + .first(States.STATE20, guardEventHeaderEquals("header1", "foo")) + .last(States.STATE16) + .and() + .withChoice() + .source(States.STATE18) + .first(States.STATE19, guardVarEquals("value3")) + .last(States.STATE20) + .and() + .withChoice() + .source(States.STATE19) + .first(States.STATE1, guardVarEquals("reset")) + .last(States.STATE20) + .and() + .withChoice() + .source(States.STATE20) + .first(States.STATE5, guardEventHeaderEquals("header2", "bar")) + .last(States.STATE1) + .and() + .withChoice() + .source(States.STATE11) + .first(States.STATE13, guardVarEquals("goTo13")) + .then(States.STATE14, guardVarEquals("goTo14")) + .last(States.STATE15) + .and() + .withChoice() + .source(States.STATE12) + .first(States.STATE10, guardVarEquals("goBack10")) + .last(States.STATE11) + .and() + .withChoice() + .source(States.STATE14) + .first(States.STATE12, guardVarEquals("loop12")) + .last(States.STATE16) + .and() + .withChoice() + .source(States.STATE9) + .first(States.STATE8, guardVarEquals("stepBack")) + .then(States.STATE7, guardVarEquals("stepBackMore")) + .last(States.STATE6) + .and() + .withChoice() + .source(States.STATE8) + .first(States.STATE9, guardVarEquals("forward9")) + .last(States.STATE10); + + addAdditionalTransitions(t1); + + addAdditionalCancellationTransitions(transitions); + } + + protected Guard guardVarEquals(String expected) { + return context -> { + Object var = context.getExtendedState().getVariables().get("var"); + return expected.equals(var); + }; + } + + protected Guard guardEventHeaderEquals(String headerName, String expected) { + return context -> { + Object header = context.getMessageHeader(headerName); + return expected.equals(header); + }; + } + + private Action logEntryAction(String msg) { + return context -> System.out.println(msg); + } + + private Action logExitAction(String msg) { + return context -> System.out.println(msg); + } +} diff --git a/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/AbstractStateMachineConfiguration.java b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/AbstractStateMachineConfiguration.java new file mode 100644 index 0000000..1ad1533 --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/AbstractStateMachineConfiguration.java @@ -0,0 +1,27 @@ +package click.kamil.examples.statemachine.inheritanceextrafunctionsstate3; + +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.config.configurers.ExternalTransitionConfigurer; + +import java.util.function.Consumer; +import java.util.stream.Stream; + +class AbstractStateMachineConfiguration extends StateMachineConfigurerAdapter { + protected void addTransitionForMultipleEvents( + StateMachineTransitionConfigurer transitions, + S source, + S target, + Consumer> transitionCustomizer, + E... events) { + Stream.of(events).forEach(event -> { + try { + ExternalTransitionConfigurer transitionConfigurer = + transitions.withExternal().event(event).source(source).target(target); + transitionCustomizer.accept(transitionConfigurer); + } catch (Exception e) { + throw new IllegalStateException(e); + } + }); + } +} diff --git a/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/Events.java b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/Events.java new file mode 100644 index 0000000..07b69f8 --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/Events.java @@ -0,0 +1,9 @@ +package click.kamil.examples.statemachine.inheritanceextrafunctionsstate3; + +public enum Events { + EVENT1, EVENT2, EVENT3, EVENT4, EVENT5, + EVENT6, EVENT7, EVENT8, EVENT9, EVENT10, + EVENT11, EVENT12, EVENT13, EVENT14, EVENT15, + EVENTX, EVENTY, EVENTZ, EVENT_CANCEL, EVENT_CANCEL_2, + EVENT_1_1, EVENT_1_2, EVENT_1_3, EVENT_1_4, EVENT_1_5 +} diff --git a/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/F1StateMachineConfiguration.java b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/F1StateMachineConfiguration.java new file mode 100644 index 0000000..af7b4db --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/F1StateMachineConfiguration.java @@ -0,0 +1,40 @@ +package click.kamil.examples.statemachine.inheritanceextrafunctionsstate3; + +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.config.configurers.ExternalTransitionConfigurer; +import org.springframework.statemachine.config.configurers.StateConfigurer; + +class F1StateMachineConfiguration extends AbstractFStateMachineConfiguration { + @Override + protected void addAdditionalStates(StateConfigurer states) { + states.state(States.STATE_EXTRA_1); + states.state(States.STATE_EXTRA_2); + states.state(States.STATE_EXTRA_3); + } + + @Override + protected void addAdditionalCancellationTransitions(StateMachineTransitionConfigurer transitions) { + addAllCancellationTransitionsForSource(transitions, States.STATE_EXTRA_1); + addAllCancellationTransitionsForSource(transitions, States.STATE_EXTRA_2); + } + + @Override + protected void addAdditionalTransitions(ExternalTransitionConfigurer transitions) throws Exception { + transitions + .and() + .withExternal().event(Events.EVENTX) + .source(States.STATE2) + .target(States.STATE_EXTRA_1) + .and() + .withChoice() + .source(States.STATE2) + .first(States.STATE1, guardEventHeaderEquals("header1", "foo")) + .last(States.STATE_EXTRA_1) + .and() + .withExternal() + .source(States.STATE_EXTRA_1) + .event(Events.EVENTY) + .target(States.STATE_EXTRA_3); + } + +} diff --git a/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/States.java b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/States.java new file mode 100644 index 0000000..60581ea --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/States.java @@ -0,0 +1,12 @@ +package click.kamil.examples.statemachine.inheritanceextrafunctionsstate3; + +public enum States { + STATE1, STATE2, STATE3, STATE4, STATE5, + STATE6, STATE7, STATE8, STATE9, STATE10, + STATE11, STATE12, STATE13, STATE14, STATE15, + STATE16, STATE17, STATE18, STATE19, STATE20, + STATEX, STATEY, STATEZ, + STATE_EXTRA_1, STATE_EXTRA_2, STATE_EXTRA_3, + STATE_EXTRA_1_1, STATE_EXTRA_1_2, STATE_EXTRA_1_3, + CANCEL +} diff --git a/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/app/StateMachineApplication.java b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/app/StateMachineApplication.java new file mode 100644 index 0000000..30d6d70 --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/src/main/java/click/kamil/examples/statemachine/inheritanceextrafunctionsstate3/app/StateMachineApplication.java @@ -0,0 +1,11 @@ +package click.kamil.examples.statemachine.inheritanceextrafunctionsstate3.app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +class StateMachineApplication { + public static void main(String[] args) { + SpringApplication.run(StateMachineApplication.class, args); + } +} diff --git a/state_machines/inheritance_extra_functions3_state_machine/src/main/resources/application.properties b/state_machines/inheritance_extra_functions3_state_machine/src/main/resources/application.properties new file mode 100644 index 0000000..1cd01ff --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.application.name=statemachinedemo diff --git a/state_machines/inheritance_extra_functions3_state_machine/src/test/java/click/kamil/examples/statemachine/MyTest.java b/state_machines/inheritance_extra_functions3_state_machine/src/test/java/click/kamil/examples/statemachine/MyTest.java new file mode 100644 index 0000000..95af6f1 --- /dev/null +++ b/state_machines/inheritance_extra_functions3_state_machine/src/test/java/click/kamil/examples/statemachine/MyTest.java @@ -0,0 +1,11 @@ +package click.kamil.examples.statemachine; + +import org.junit.jupiter.api.Test; + +class MyTest { + + @Test + void contextLoads() { + } + +}