From de556f0d54ca4404042233d08b9ac42b6597f809 Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Sat, 1 Oct 2016 09:34:31 +0100 Subject: [PATCH] Add repository config substates - Add parent state to RepositoryState and use it in model factory. - Relates to #262 --- spring-statemachine-data/build.gradle | 2 + .../data/jpa/JpaRepositoryState.java | 23 ++++ .../data/jpa/AbstractJpaRepositoryTests.java | 47 ++++++++ .../data/jpa/JpaRepositoryTests.java | 111 ++++++++++++++++-- .../jpa/src/test/resources/data2.json | 29 +++++ .../jpa/src/test/resources/data3.json | 48 ++++++++ .../statemachine/data/RepositoryState.java | 7 ++ .../RepositoryStateMachineModelFactory.java | 2 +- 8 files changed, 261 insertions(+), 8 deletions(-) create mode 100644 spring-statemachine-data/jpa/src/test/java/org/springframework/statemachine/data/jpa/AbstractJpaRepositoryTests.java create mode 100644 spring-statemachine-data/jpa/src/test/resources/data2.json create mode 100644 spring-statemachine-data/jpa/src/test/resources/data3.json diff --git a/spring-statemachine-data/build.gradle b/spring-statemachine-data/build.gradle index c84e0171..7614460b 100644 --- a/spring-statemachine-data/build.gradle +++ b/spring-statemachine-data/build.gradle @@ -6,7 +6,9 @@ project('spring-statemachine-data-jpa') { compile project(":spring-statemachine-data-common") compile "org.springframework:spring-orm:$springVersion" optional "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion" + testCompile project(":spring-statemachine-test") testCompile "org.hsqldb:hsqldb:$hsqlVersion" testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion" + testRuntime "org.springframework.boot:spring-boot-starter-web:$springBootVersion" } } diff --git a/spring-statemachine-data/jpa/src/main/java/org/springframework/statemachine/data/jpa/JpaRepositoryState.java b/spring-statemachine-data/jpa/src/main/java/org/springframework/statemachine/data/jpa/JpaRepositoryState.java index b9d83c62..92ea5e0d 100644 --- a/spring-statemachine-data/jpa/src/main/java/org/springframework/statemachine/data/jpa/JpaRepositoryState.java +++ b/spring-statemachine-data/jpa/src/main/java/org/springframework/statemachine/data/jpa/JpaRepositoryState.java @@ -36,6 +36,7 @@ public class JpaRepositoryState implements RepositoryState { private long id; private String machineId; + private String parentState; private String state; private boolean initial; @@ -72,7 +73,20 @@ public class JpaRepositoryState implements RepositoryState { * @param initial the initial */ public JpaRepositoryState(String machineId, String state, boolean initial) { + this(machineId, null, state, initial); + } + + /** + * Instantiates a new jpa repository state. + * + * @param machineId the machine id + * @param parentState the parent state + * @param state the state + * @param initial the initial + */ + public JpaRepositoryState(String machineId, String parentState, String state, boolean initial) { this.machineId = machineId; + this.parentState = parentState; this.state = state; this.initial = initial; } @@ -86,6 +100,15 @@ public class JpaRepositoryState implements RepositoryState { this.machineId = machineId; } + @Override + public String getParentState() { + return parentState; + } + + public void setParentState(String parentState) { + this.parentState = parentState; + } + @Override public String getState() { return state; diff --git a/spring-statemachine-data/jpa/src/test/java/org/springframework/statemachine/data/jpa/AbstractJpaRepositoryTests.java b/spring-statemachine-data/jpa/src/test/java/org/springframework/statemachine/data/jpa/AbstractJpaRepositoryTests.java new file mode 100644 index 00000000..cee49463 --- /dev/null +++ b/spring-statemachine-data/jpa/src/test/java/org/springframework/statemachine/data/jpa/AbstractJpaRepositoryTests.java @@ -0,0 +1,47 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.statemachine.data.jpa; + +import org.junit.After; +import org.junit.Before; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public abstract class AbstractJpaRepositoryTests { + + protected AnnotationConfigApplicationContext context; + + @Before + public void setup() { + context = buildContext(); + } + + @After + public void clean() { + if (context != null) { + context.close(); + } + context = null; + } + + /** + * Builds the context. + * + * @return the annotation config application context + */ + protected AnnotationConfigApplicationContext buildContext() { + return null; + } +} diff --git a/spring-statemachine-data/jpa/src/test/java/org/springframework/statemachine/data/jpa/JpaRepositoryTests.java b/spring-statemachine-data/jpa/src/test/java/org/springframework/statemachine/data/jpa/JpaRepositoryTests.java index b2ce05af..ea2e4cf4 100644 --- a/spring-statemachine-data/jpa/src/test/java/org/springframework/statemachine/data/jpa/JpaRepositoryTests.java +++ b/spring-statemachine-data/jpa/src/test/java/org/springframework/statemachine/data/jpa/JpaRepositoryTests.java @@ -24,17 +24,34 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.data.repository.init.Jackson2RepositoryPopulatorFactoryBean; +import org.springframework.statemachine.StateMachine; +import org.springframework.statemachine.config.EnableStateMachineFactory; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.StateMachineFactory; +import org.springframework.statemachine.config.builders.StateMachineModelConfigurer; +import org.springframework.statemachine.config.model.StateMachineModelFactory; import org.springframework.statemachine.data.RepositoryState; -import org.springframework.statemachine.data.StateRepository; +import org.springframework.statemachine.data.RepositoryStateMachineModelFactory; import org.springframework.statemachine.data.RepositoryTransition; +import org.springframework.statemachine.data.StateRepository; import org.springframework.statemachine.data.TransitionRepository; +import org.springframework.statemachine.test.StateMachineTestPlan; +import org.springframework.statemachine.test.StateMachineTestPlanBuilder; -public class JpaRepositoryTests { +public class JpaRepositoryTests extends AbstractJpaRepositoryTests { + + @Override + protected AnnotationConfigApplicationContext buildContext() { + return new AnnotationConfigApplicationContext(); + } @Test public void testRepository1() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Config.class); context.refresh(); @@ -57,7 +74,6 @@ public class JpaRepositoryTests { @Test public void testRepository2() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Config.class); context.refresh(); @@ -84,7 +100,6 @@ public class JpaRepositoryTests { @Test public void testRepository3() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Config.class); context.refresh(); @@ -118,12 +133,48 @@ public class JpaRepositoryTests { context.close(); } + @SuppressWarnings("unchecked") + @Test + public void testMachine2() throws Exception { + context.register(Config2.class, FactoryConfig.class); + context.refresh(); + StateMachineFactory stateMachineFactory = context.getBean(StateMachineFactory.class); + StateMachine stateMachine = stateMachineFactory.getStateMachine(); + + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder() + .stateMachine(stateMachine) + .step().expectStates("S1").and() + .step().sendEvent("E1").expectStates("S2").and() + .step().sendEvent("E2").expectStates("S3").and() + .build(); + plan.test(); + } + + @SuppressWarnings("unchecked") + @Test + public void testMachine3() throws Exception { + context.register(Config3.class, FactoryConfig.class); + context.refresh(); + StateMachineFactory stateMachineFactory = context.getBean(StateMachineFactory.class); + StateMachine stateMachine = stateMachineFactory.getStateMachine(); + + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder() + .stateMachine(stateMachine) + .step().expectStates("S1").and() + .step().sendEvent("E1").expectStates("S2", "S20").and() + .step().sendEvent("E2").expectStates("S2", "S21").and() + .step().sendEvent("E3").expectStates("S1").and() + .step().sendEvent("E4").expectStates("S2", "S21").and() + .build(); + plan.test(); + } + @Test public void testAutowire() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Config.class, WireConfig.class); context.refresh(); - context.close(); } @EnableAutoConfiguration @@ -149,4 +200,50 @@ public class JpaRepositoryTests { @Autowired StateRepository statesRepository4; } + + @EnableAutoConfiguration + static class Config2 { + + @Bean + public Jackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() { + Jackson2RepositoryPopulatorFactoryBean factoryBean = new Jackson2RepositoryPopulatorFactoryBean(); + factoryBean.setResources(new Resource[]{new ClassPathResource("data2.json")}); + return factoryBean; + } + } + + @EnableAutoConfiguration + static class Config3 { + + @Bean + public Jackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() { + Jackson2RepositoryPopulatorFactoryBean factoryBean = new Jackson2RepositoryPopulatorFactoryBean(); + factoryBean.setResources(new Resource[]{new ClassPathResource("data3.json")}); + return factoryBean; + } + } + + @Configuration + @EnableStateMachineFactory + public static class FactoryConfig extends StateMachineConfigurerAdapter { + + @Autowired + private StateRepository stateRepository; + + @Autowired + private TransitionRepository transitionRepository; + + @Override + public void configure(StateMachineModelConfigurer model) throws Exception { + model + .withModel() + .factory(modelFactory()); + } + + @Bean + public StateMachineModelFactory modelFactory() { + return new RepositoryStateMachineModelFactory(stateRepository, transitionRepository); + } + } + } diff --git a/spring-statemachine-data/jpa/src/test/resources/data2.json b/spring-statemachine-data/jpa/src/test/resources/data2.json new file mode 100644 index 00000000..2cdfb1d6 --- /dev/null +++ b/spring-statemachine-data/jpa/src/test/resources/data2.json @@ -0,0 +1,29 @@ +[ + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": true, + "state": "S1" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": false, + "state": "S2" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": false, + "state": "S3" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition", + "source": "S1", + "target": "S2", + "event": "E1" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition", + "source": "S2", + "target": "S3", + "event": "E2" + } +] diff --git a/spring-statemachine-data/jpa/src/test/resources/data3.json b/spring-statemachine-data/jpa/src/test/resources/data3.json new file mode 100644 index 00000000..88e66ab9 --- /dev/null +++ b/spring-statemachine-data/jpa/src/test/resources/data3.json @@ -0,0 +1,48 @@ +[ + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": true, + "state": "S1" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": false, + "state": "S2" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": true, + "parentState": "S2", + "state": "S20" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState", + "initial": false, + "parentState": "S2", + "state": "S21" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition", + "source": "S1", + "target": "S2", + "event": "E1" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition", + "source": "S20", + "target": "S21", + "event": "E2" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition", + "source": "S2", + "target": "S1", + "event": "E3" + }, + { + "_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition", + "source": "S1", + "target": "S21", + "event": "E4" + } +] diff --git a/spring-statemachine-data/src/main/java/org/springframework/statemachine/data/RepositoryState.java b/spring-statemachine-data/src/main/java/org/springframework/statemachine/data/RepositoryState.java index 1f5c1342..c3152b95 100644 --- a/spring-statemachine-data/src/main/java/org/springframework/statemachine/data/RepositoryState.java +++ b/spring-statemachine-data/src/main/java/org/springframework/statemachine/data/RepositoryState.java @@ -23,6 +23,13 @@ package org.springframework.statemachine.data; */ public interface RepositoryState { + /** + * Gets the parent state. + * + * @return the parent state + */ + String getParentState(); + /** * Gets the machine id. * 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 a6dabdb3..cc9f54f2 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 @@ -62,7 +62,7 @@ public class RepositoryStateMachineModelFactory implements StateMachineModelFact Collection> stateData = new ArrayList<>(); for (RepositoryState s : stateRepository.findByMachineId(machineId)) { - stateData.add(new StateData(s.getState(), s.isInitial())); + stateData.add(new StateData(s.getParentState(), null, s.getState(), s.isInitial())); } StatesData statesData = new StatesData<>(stateData);