Add initial action to repository config
- Now RepositoryState can have initial action if it is an initial state. - Implement all needed tests. - Fixes #281
This commit is contained in:
@@ -109,6 +109,23 @@ public class StateData<S, E> {
|
||||
*/
|
||||
public StateData(Object parent, Object region, S state, Collection<E> deferred,
|
||||
Collection<? extends Action<S, E>> entryActions, Collection<? extends Action<S, E>> exitActions, boolean initial) {
|
||||
this(parent, region, state, deferred, entryActions, exitActions, initial, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new state data.
|
||||
*
|
||||
* @param parent the parent
|
||||
* @param region the region
|
||||
* @param state the state
|
||||
* @param deferred the deferred
|
||||
* @param entryActions the entry actions
|
||||
* @param exitActions the exit actions
|
||||
* @param initial the initial
|
||||
* @param initialAction the initial action
|
||||
*/
|
||||
public StateData(Object parent, Object region, S state, Collection<E> deferred,
|
||||
Collection<? extends Action<S, E>> entryActions, Collection<? extends Action<S, E>> exitActions, boolean initial, Action<S, E> initialAction) {
|
||||
this.state = state;
|
||||
this.deferred = deferred;
|
||||
this.entryActions = entryActions;
|
||||
@@ -116,6 +133,7 @@ public class StateData<S, E> {
|
||||
this.parent = parent;
|
||||
this.region = region;
|
||||
this.initial = initial;
|
||||
this.initialAction = initialAction;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.persistence.Id;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
import org.springframework.statemachine.data.RepositoryAction;
|
||||
import org.springframework.statemachine.data.RepositoryState;
|
||||
import org.springframework.statemachine.state.PseudoStateKind;
|
||||
|
||||
@@ -53,6 +54,9 @@ public class JpaRepositoryState extends RepositoryState {
|
||||
private PseudoStateKind kind;
|
||||
private String submachineId;
|
||||
|
||||
@OneToOne(fetch = FetchType.EAGER)
|
||||
private JpaRepositoryAction initialAction;
|
||||
|
||||
@OneToOne(fetch = FetchType.EAGER)
|
||||
private JpaRepositoryState parentState;
|
||||
|
||||
@@ -193,6 +197,15 @@ public class JpaRepositoryState extends RepositoryState {
|
||||
this.initial = initial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryAction getInitialAction() {
|
||||
return initialAction;
|
||||
}
|
||||
|
||||
public void setInitialAction(JpaRepositoryAction initialAction) {
|
||||
this.initialAction = initialAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<JpaRepositoryAction> getStateActions() {
|
||||
return stateActions;
|
||||
|
||||
27
spring-statemachine-data/jpa/src/test/resources/data14.json
Normal file
27
spring-statemachine-data/jpa/src/test/resources/data14.json
Normal file
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"@id": "1",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryAction",
|
||||
"spel": "extendedState.variables.put('foo', 0)"
|
||||
},
|
||||
{
|
||||
"@id": "2",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": true,
|
||||
"initialAction" : "1",
|
||||
"state": "S1"
|
||||
},
|
||||
{
|
||||
"@id": "3",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S2"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "2",
|
||||
"target": "3",
|
||||
"event": "E1",
|
||||
"kind": "EXTERNAL"
|
||||
}
|
||||
]
|
||||
@@ -20,6 +20,7 @@ import java.util.Set;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Reference;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.statemachine.data.RepositoryAction;
|
||||
import org.springframework.statemachine.data.RepositoryState;
|
||||
import org.springframework.statemachine.state.PseudoStateKind;
|
||||
|
||||
@@ -49,6 +50,9 @@ public class MongoDbRepositoryState extends RepositoryState {
|
||||
@Reference
|
||||
private MongoDbRepositoryState parentState;
|
||||
|
||||
@Reference
|
||||
private MongoDbRepositoryAction initialAction;
|
||||
|
||||
@Reference
|
||||
private Set<MongoDbRepositoryAction> stateActions;
|
||||
|
||||
@@ -184,6 +188,15 @@ public class MongoDbRepositoryState extends RepositoryState {
|
||||
this.initial = initial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryAction getInitialAction() {
|
||||
return initialAction;
|
||||
}
|
||||
|
||||
public void setInitialAction(MongoDbRepositoryAction initialAction) {
|
||||
this.initialAction = initialAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MongoDbRepositoryAction> getStateActions() {
|
||||
return stateActions;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"@id": "1",
|
||||
"_class": "org.springframework.statemachine.data.mongodb.MongoDbRepositoryAction",
|
||||
"spel": "extendedState.variables.put('foo', 0)"
|
||||
},
|
||||
{
|
||||
"@id": "2",
|
||||
"_class": "org.springframework.statemachine.data.mongodb.MongoDbRepositoryState",
|
||||
"initial": true,
|
||||
"initialAction" : "1",
|
||||
"state": "S1"
|
||||
},
|
||||
{
|
||||
"@id": "3",
|
||||
"_class": "org.springframework.statemachine.data.mongodb.MongoDbRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S2"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.mongodb.MongoDbRepositoryTransition",
|
||||
"source": "2",
|
||||
"target": "3",
|
||||
"event": "E1",
|
||||
"kind": "EXTERNAL"
|
||||
}
|
||||
]
|
||||
@@ -29,6 +29,7 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Reference;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
import org.springframework.data.redis.core.index.Indexed;
|
||||
import org.springframework.statemachine.data.RepositoryAction;
|
||||
import org.springframework.statemachine.data.RepositoryState;
|
||||
import org.springframework.statemachine.state.PseudoStateKind;
|
||||
|
||||
@@ -59,6 +60,9 @@ public class RedisRepositoryState extends RepositoryState {
|
||||
@Reference
|
||||
private RedisRepositoryState parentState;
|
||||
|
||||
@Reference
|
||||
private RedisRepositoryAction initialAction;
|
||||
|
||||
@Reference
|
||||
private Set<RedisRepositoryAction> stateActions;
|
||||
|
||||
@@ -194,6 +198,15 @@ public class RedisRepositoryState extends RepositoryState {
|
||||
this.initial = initial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryAction getInitialAction() {
|
||||
return initialAction;
|
||||
}
|
||||
|
||||
public void setInitialAction(RedisRepositoryAction initialAction) {
|
||||
this.initialAction = initialAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RedisRepositoryAction> getStateActions() {
|
||||
return stateActions;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"@id": "1",
|
||||
"_class": "org.springframework.statemachine.data.redis.RedisRepositoryAction",
|
||||
"spel": "extendedState.variables.put('foo', 0)"
|
||||
},
|
||||
{
|
||||
"@id": "2",
|
||||
"_class": "org.springframework.statemachine.data.redis.RedisRepositoryState",
|
||||
"initial": true,
|
||||
"initialAction" : "1",
|
||||
"state": "S1"
|
||||
},
|
||||
{
|
||||
"@id": "3",
|
||||
"_class": "org.springframework.statemachine.data.redis.RedisRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S2"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.redis.RedisRepositoryTransition",
|
||||
"source": "2",
|
||||
"target": "3",
|
||||
"event": "E1",
|
||||
"kind": "EXTERNAL"
|
||||
}
|
||||
]
|
||||
@@ -62,6 +62,14 @@ public abstract class RepositoryState extends BaseRepositoryEntity {
|
||||
*/
|
||||
public abstract boolean isInitial();
|
||||
|
||||
/**
|
||||
* Gets the initial action. This is any meaningful if
|
||||
* state is initial state.
|
||||
*
|
||||
* @return the initial action
|
||||
*/
|
||||
public abstract RepositoryAction getInitialAction();
|
||||
|
||||
/**
|
||||
* Gets the state actions.
|
||||
*
|
||||
|
||||
@@ -153,6 +153,18 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
|
||||
Object region = s.getRegion();
|
||||
StateData<String, String> stateData = new StateData<String, String>(parentState != null ? parentState.getState() : null, region,
|
||||
s.getState(), s.isInitial());
|
||||
Action<String, String> initialAction = null;
|
||||
if (s.getInitialAction() != null) {
|
||||
if (StringUtils.hasText(s.getInitialAction().getName())) {
|
||||
initialAction = resolveAction(s.getInitialAction().getName());
|
||||
} else if (StringUtils.hasText(s.getInitialAction().getSpel())) {
|
||||
SpelExpressionParser parser = new SpelExpressionParser(
|
||||
new SpelParserConfiguration(SpelCompilerMode.MIXED, null));
|
||||
|
||||
initialAction = new SpelExpressionAction<String, String>(parser.parseExpression(s.getInitialAction().getSpel()));
|
||||
}
|
||||
}
|
||||
stateData.setInitialAction(initialAction);
|
||||
stateData.setStateActions(stateActions);
|
||||
stateData.setEntryActions(entryActions);
|
||||
stateData.setExitActions(exitActions);
|
||||
@@ -170,7 +182,7 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
|
||||
Collection<StateData<String, String>> submachineStateDataOrig = subStateMachineModel.getStatesData().getStateData();
|
||||
for (StateData<String, String> sd : submachineStateDataOrig) {
|
||||
submachineStateData.add(new StateData<String, String>(s.getState(), sd.getRegion(), sd.getState(),
|
||||
sd.getDeferred(), sd.getEntryActions(), sd.getExitActions(), sd.isInitial()));
|
||||
sd.getDeferred(), sd.getEntryActions(), sd.getExitActions(), sd.isInitial(), sd.getInitialAction()));
|
||||
}
|
||||
stateData.setSubmachineStateData(submachineStateData);
|
||||
}
|
||||
|
||||
@@ -412,6 +412,24 @@ public abstract class AbstractRepositoryTests {
|
||||
plan.test();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testMachine14() throws Exception {
|
||||
context.register(getRegisteredClasses());
|
||||
context.register(Config14.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").expectVariable("foo", 0).and()
|
||||
.step().sendEvent("E1").expectStates("S2").and()
|
||||
.build();
|
||||
plan.test();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class Config2 {
|
||||
|
||||
@@ -576,6 +594,17 @@ public abstract class AbstractRepositoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class Config14 {
|
||||
|
||||
@Bean
|
||||
public StateMachineJackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
|
||||
StateMachineJackson2RepositoryPopulatorFactoryBean factoryBean = new StateMachineJackson2RepositoryPopulatorFactoryBean();
|
||||
factoryBean.setResources(new Resource[]{new ClassPathResource("data14.json")});
|
||||
return factoryBean;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachineFactory
|
||||
public static class FactoryConfig extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
Reference in New Issue
Block a user