Add repository config substates
- Add parent state to RepositoryState and use it in model factory. - Relates to #262
This commit is contained in:
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> stateMachineFactory = context.getBean(StateMachineFactory.class);
|
||||
StateMachine<String, String> stateMachine = stateMachineFactory.getStateMachine();
|
||||
|
||||
StateMachineTestPlan<String, String> plan =
|
||||
StateMachineTestPlanBuilder.<String, String>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<String, String> stateMachineFactory = context.getBean(StateMachineFactory.class);
|
||||
StateMachine<String, String> stateMachine = stateMachineFactory.getStateMachine();
|
||||
|
||||
StateMachineTestPlan<String, String> plan =
|
||||
StateMachineTestPlanBuilder.<String, String>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<? extends RepositoryState> 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<String, String> {
|
||||
|
||||
@Autowired
|
||||
private StateRepository<? extends RepositoryState> stateRepository;
|
||||
|
||||
@Autowired
|
||||
private TransitionRepository<? extends RepositoryTransition> transitionRepository;
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
|
||||
model
|
||||
.withModel()
|
||||
.factory(modelFactory());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StateMachineModelFactory<String, String> modelFactory() {
|
||||
return new RepositoryStateMachineModelFactory(stateRepository, transitionRepository);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
29
spring-statemachine-data/jpa/src/test/resources/data2.json
Normal file
29
spring-statemachine-data/jpa/src/test/resources/data2.json
Normal file
@@ -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"
|
||||
}
|
||||
]
|
||||
48
spring-statemachine-data/jpa/src/test/resources/data3.json
Normal file
48
spring-statemachine-data/jpa/src/test/resources/data3.json
Normal file
@@ -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"
|
||||
}
|
||||
]
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -62,7 +62,7 @@ public class RepositoryStateMachineModelFactory implements StateMachineModelFact
|
||||
|
||||
Collection<StateData<String, String>> stateData = new ArrayList<>();
|
||||
for (RepositoryState s : stateRepository.findByMachineId(machineId)) {
|
||||
stateData.add(new StateData<String, String>(s.getState(), s.isInitial()));
|
||||
stateData.add(new StateData<String, String>(s.getParentState(), null, s.getState(), s.isInitial()));
|
||||
}
|
||||
StatesData<String, String> statesData = new StatesData<>(stateData);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user