From a8a842fc2aaff92ef25311c002ea9ac31e760ca7 Mon Sep 17 00:00:00 2001 From: Adar Wesley Date: Mon, 19 Aug 2019 17:44:10 +0300 Subject: [PATCH] Fix action loading in uml - Refactored actions loading code to eliminate duplicated code. - Added relevant test case. - Fixes #588 --- .../jpa/src/test/resources/data15.json | 39 +++++++++ .../RepositoryStateMachineModelFactory.java | 82 +++++++------------ .../data/AbstractRepositoryTests.java | 36 ++++++++ 3 files changed, 103 insertions(+), 54 deletions(-) create mode 100644 spring-statemachine-data/jpa/src/test/resources/data15.json diff --git a/spring-statemachine-data/jpa/src/test/resources/data15.json b/spring-statemachine-data/jpa/src/test/resources/data15.json new file mode 100644 index 00000000..f756a03b --- /dev/null +++ b/spring-statemachine-data/jpa/src/test/resources/data15.json @@ -0,0 +1,39 @@ +[ + { + "@id": "3", + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryAction", + "spel": "false" + }, + { + "@id": "4", + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryAction", + "spel": "false" + }, + { + "@id": "5", + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryAction", + "spel": "false" + }, + { + "@id": "1", + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": true, + "state": "S1", + "exitActions": ["3"] + }, + { + "@id": "2", + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": false, + "state": "S2", + "entryActions": ["4"], + "stateActions": ["5"] + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition", + "source": "1", + "target": "2", + "event": "E1", + "kind": "EXTERNAL" + } +] \ No newline at end of file diff --git a/spring-statemachine-data/src/main/java/org/springframework/statemachine/data/RepositoryStateMachineModelFactory.java b/spring-statemachine-data/src/main/java/org/springframework/statemachine/data/RepositoryStateMachineModelFactory.java index 09178ec0..23dc16e0 100644 --- a/spring-statemachine-data/src/main/java/org/springframework/statemachine/data/RepositoryStateMachineModelFactory.java +++ b/spring-statemachine-data/src/main/java/org/springframework/statemachine/data/RepositoryStateMachineModelFactory.java @@ -95,62 +95,14 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode subStateMachineModel = build(submachineId); } - Collection, Mono>> stateActions = new ArrayList<>(); - Set repositoryStateActions = s.getStateActions(); - if (repositoryStateActions != null) { - for (RepositoryAction repositoryAction : repositoryStateActions) { - Action action = null; - if (StringUtils.hasText(repositoryAction.getName())) { - action = resolveAction(repositoryAction.getName()); - } else if (StringUtils.hasText(repositoryAction.getSpel())) { - SpelExpressionParser parser = new SpelExpressionParser( - new SpelParserConfiguration(SpelCompilerMode.MIXED, null)); + Collection, Mono>> stateActions = + loadStateActionsFromRepositoryState(s.getStateActions()); - action = new SpelExpressionAction(parser.parseExpression(repositoryAction.getSpel())); - } - if (action != null) { - stateActions.add(Actions.from(action)); - } - } - } + Collection, Mono>> entryActions = + loadStateActionsFromRepositoryState(s.getEntryActions()); - Collection, Mono>> entryActions = new ArrayList<>(); - Set repositoryEntryActions = s.getEntryActions(); - if (repositoryEntryActions != null) { - for (RepositoryAction repositoryAction : repositoryEntryActions) { - Action action = null; - if (StringUtils.hasText(repositoryAction.getName())) { - action = resolveAction(repositoryAction.getName()); - } else if (StringUtils.hasText(repositoryAction.getSpel())) { - SpelExpressionParser parser = new SpelExpressionParser( - new SpelParserConfiguration(SpelCompilerMode.MIXED, null)); - - action = new SpelExpressionAction(parser.parseExpression(repositoryAction.getSpel())); - } - if (action != null) { - stateActions.add(Actions.from(action)); - } - } - } - - Collection, Mono>> exitActions = new ArrayList<>(); - Set repositoryExitActions = s.getExitActions(); - if (repositoryExitActions != null) { - for (RepositoryAction repositoryAction : repositoryExitActions) { - Action action = null; - if (StringUtils.hasText(repositoryAction.getName())) { - action = resolveAction(repositoryAction.getName()); - } else if (StringUtils.hasText(repositoryAction.getSpel())) { - SpelExpressionParser parser = new SpelExpressionParser( - new SpelParserConfiguration(SpelCompilerMode.MIXED, null)); - - action = new SpelExpressionAction(parser.parseExpression(repositoryAction.getSpel())); - } - if (action != null) { - stateActions.add(Actions.from(action)); - } - } - } + Collection, Mono>> exitActions = + loadStateActionsFromRepositoryState(s.getExitActions()); RepositoryState parentState = s.getParentState(); Object region = s.getRegion(); @@ -291,6 +243,28 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode return new DefaultStateMachineModel<>(null, statesData, transitionsData); } + private Collection, Mono>> loadStateActionsFromRepositoryState( + Set repositoryStateActions) { + Collection, Mono>> stateActions = new ArrayList<>(); + if (repositoryStateActions != null) { + for (RepositoryAction repositoryAction : repositoryStateActions) { + Action action = null; + if (StringUtils.hasText(repositoryAction.getName())) { + action = resolveAction(repositoryAction.getName()); + } else if (StringUtils.hasText(repositoryAction.getSpel())) { + SpelExpressionParser parser = new SpelExpressionParser( + new SpelParserConfiguration(SpelCompilerMode.MIXED, null)); + + action = new SpelExpressionAction(parser.parseExpression(repositoryAction.getSpel())); + } + if (action != null) { + stateActions.add(Actions.from(action)); + } + } + } + return stateActions; + } + private Guard resolveGuard(RepositoryTransition t) { Guard guard = null; RepositoryGuard repositoryGuard = t.getGuard(); diff --git a/spring-statemachine-data/src/test/java/org/springframework/statemachine/data/AbstractRepositoryTests.java b/spring-statemachine-data/src/test/java/org/springframework/statemachine/data/AbstractRepositoryTests.java index f68ae293..480ce21c 100644 --- a/spring-statemachine-data/src/test/java/org/springframework/statemachine/data/AbstractRepositoryTests.java +++ b/spring-statemachine-data/src/test/java/org/springframework/statemachine/data/AbstractRepositoryTests.java @@ -18,8 +18,13 @@ package org.springframework.statemachine.data; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; import org.junit.After; import org.junit.Before; @@ -430,6 +435,26 @@ public abstract class AbstractRepositoryTests { plan.test(); } + @SuppressWarnings("unchecked") + @Test + public void testMachine15() throws Exception { + context.register(getRegisteredClasses()); + context.register(Config15.class, FactoryConfig.class); + context.refresh(); + StateMachineFactory stateMachineFactory = context.getBean(StateMachineFactory.class); + StateMachine stateMachine = stateMachineFactory.getStateMachine(); + + Map> states = stateMachine.getStates().stream().collect(Collectors.toMap((State s1) -> s1.getId(), s2 -> s2)); + assertEquals(2, states.size()); + + State S1 = (State) states.get("S1"); + assertEquals(1, S1.getExitActions().size()); + + State S2 = (State)states.get("S2"); + assertEquals(1, S2.getEntryActions().size()); + assertEquals(1, S2.getStateActions().size()); + } + @Configuration public static class Config2 { @@ -605,6 +630,17 @@ public abstract class AbstractRepositoryTests { } } + @Configuration + public static class Config15 { + + @Bean + public StateMachineJackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() { + StateMachineJackson2RepositoryPopulatorFactoryBean factoryBean = new StateMachineJackson2RepositoryPopulatorFactoryBean(); + factoryBean.setResources(new Resource[]{new ClassPathResource("data15.json")}); + return factoryBean; + } + } + @Configuration @EnableStateMachineFactory public static class FactoryConfig extends StateMachineConfigurerAdapter {