Add support for multiple end states with javaconfig

- Add missing support for defining more than one
  end states and as it's just missing from javaconfig.
- Backport #368
- Relates #307
This commit is contained in:
Janne Valkealahti
2017-07-09 08:41:30 +01:00
parent 526c05e0f9
commit 1e60b7abfa
4 changed files with 115 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-2017 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.
@@ -51,7 +51,7 @@ public class DefaultStateConfigurer<S, E>
private final Map<S, StateData<S, E>> incomplete = new HashMap<S, StateData<S, E>>();
private S initialState;
private Action<S, E> initialAction;
private S end;
private final Collection<S> ends = new ArrayList<>();
private S history;
private History historyType;
private final Collection<S> choices = new ArrayList<S>();
@@ -75,7 +75,7 @@ public class DefaultStateConfigurer<S, E>
s.setInitial(true);
s.setInitialAction(initialAction);
}
if (s.getState() == end) {
if (ends.contains(s.getState())) {
s.setEnd(true);
}
if (choices.contains(s.getState())) {
@@ -125,7 +125,7 @@ public class DefaultStateConfigurer<S, E>
@Override
public StateConfigurer<S, E> end(S end) {
this.end = end;
this.ends.add(end);
state(end);
return this;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2017 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.
@@ -223,7 +223,8 @@ public interface StateConfigurer<S, E> extends
StateConfigurer<S, E> states(Set<S> states);
/**
* Specify a state {@code S} to be end state.
* Specify a state {@code S} to be end state. This method
* can be called for each state to be marked as end state.
*
* @param end the end state
* @return configurer for chaining

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2017 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.
@@ -49,6 +49,8 @@ import org.springframework.statemachine.config.builders.StateMachineConfiguratio
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.state.PseudoStateKind;
import org.springframework.statemachine.state.State;
/**
* Tests for state machine configuration.
@@ -290,6 +292,28 @@ public class ConfigurationTests extends AbstractStateMachineTests {
assertThat(stateMachine.getId(), is("testid2"));
}
@SuppressWarnings("unchecked")
@Test
public void testMultipleEndStates() {
context.register(Config20.class);
context.refresh();
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
ObjectStateMachine<String, String> machine =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
Collection<State<String, String>> states = machine.getStates();
for (State<String, String> s : states) {
if (s.getId().equals("S3")) {
assertThat(s.getPseudoState(), notNullValue());
assertThat(s.getPseudoState().getKind(), is(PseudoStateKind.END));
}
if (s.getId().equals("S2")) {
assertThat(s.getPseudoState(), notNullValue());
assertThat(s.getPseudoState().getKind(), is(PseudoStateKind.END));
}
}
}
@Configuration
@EnableStateMachine
public static class Config1 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@@ -872,4 +896,26 @@ public class ConfigurationTests extends AbstractStateMachineTests {
}
}
@Configuration
@EnableStateMachine
public static class Config20 extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
states
.withStates()
.initial("S1")
.end("S2")
.end("S3");
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
transitions
.withExternal()
.source("S1")
.target("S2")
.event("E1");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-2017 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.
@@ -133,6 +133,38 @@ public class EndStateTests extends AbstractStateMachineTests {
context.refresh();
}
@Test
public void testEndStateCompletesMultipleEndStates1() {
context.register(Config7.class);
context.refresh();
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
@SuppressWarnings("unchecked")
ObjectStateMachine<TestStates,TestEvents> machine =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
machine.start();
assertThat(machine, notNullValue());
assertThat(machine.isComplete(), is(false));
machine.sendEvent(TestEvents.E1);
assertThat(machine.isComplete(), is(true));
assertThat(machine.getState().getIds(), contains(TestStates.S1));
}
@Test
public void testEndStateCompletesMultipleEndStates2() {
context.register(Config7.class);
context.refresh();
assertTrue(context.containsBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE));
@SuppressWarnings("unchecked")
ObjectStateMachine<TestStates,TestEvents> machine =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
machine.start();
assertThat(machine, notNullValue());
assertThat(machine.isComplete(), is(false));
machine.sendEvent(TestEvents.E2);
assertThat(machine.isComplete(), is(true));
assertThat(machine.getState().getIds(), contains(TestStates.S2));
}
@Configuration
@EnableStateMachine
static class Config1 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@@ -436,4 +468,32 @@ public class EndStateTests extends AbstractStateMachineTests {
.last("SF");
}
}
@Configuration
@EnableStateMachine
static class Config7 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@Override
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
states
.withStates()
.initial(TestStates.SI)
.end(TestStates.S1)
.end(TestStates.S2);
}
@Override
public void configure(StateMachineTransitionConfigurer<TestStates, TestEvents> transitions) throws Exception {
transitions
.withExternal()
.source(TestStates.SI)
.target(TestStates.S1)
.event(TestEvents.E1)
.and()
.withExternal()
.source(TestStates.SI)
.target(TestStates.S2)
.event(TestEvents.E2);
}
}
}