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:
Janne Valkealahti
2016-11-23 13:55:52 +00:00
parent ea511b8ed8
commit 0c3ea7fb2d
10 changed files with 188 additions and 1 deletions

View File

@@ -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;
}
/**

View File

@@ -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;

View 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"
}
]

View File

@@ -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;

View File

@@ -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"
}
]

View File

@@ -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;

View File

@@ -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"
}
]

View File

@@ -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.
*

View File

@@ -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);
}

View File

@@ -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> {