Ability to set UUID for StateMachine

- Squash commits with below entries
- Add factory with a given uuid
- Fix compile error, replace spaces by tabs and clean imports
- Make more sense to swap uuid and stringId
- Fixes #241
This commit is contained in:
Christophe
2016-08-23 15:37:38 +02:00
committed by Janne Valkealahti
parent 4c34e46ccf
commit e6f10b60f5
6 changed files with 110 additions and 61 deletions

View File

@@ -15,13 +15,14 @@
*/
package org.springframework.statemachine;
import java.util.Collection;
import org.springframework.messaging.Message;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.support.AbstractStateMachine;
import org.springframework.statemachine.transition.Transition;
import java.util.Collection;
import java.util.UUID;
/**
* Specialisation of a {@link StateMachine} using objects
* as its {@link State} and event types.
@@ -54,11 +55,12 @@ public class ObjectStateMachine<S, E> extends AbstractStateMachine<S, E> {
* @param initialTransition the initial transition
* @param initialEvent the initial event
* @param extendedState the extended state
* @param uuid the given uuid.
*/
public ObjectStateMachine(Collection<State<S, E>> states, Collection<Transition<S, E>> transitions,
State<S, E> initialState, Transition<S, E> initialTransition,
Message<E> initialEvent, ExtendedState extendedState) {
super(states, transitions, initialState, initialTransition, initialEvent, extendedState);
Message<E> initialEvent, ExtendedState extendedState, UUID uuid) {
super(states, transitions, initialState, initialTransition, initialEvent, extendedState, uuid);
}
}

View File

@@ -15,6 +15,16 @@
*/
package org.springframework.statemachine.config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.UUID;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
@@ -45,27 +55,27 @@ import org.springframework.statemachine.region.Region;
import org.springframework.statemachine.security.StateMachineSecurityInterceptor;
import org.springframework.statemachine.state.AbstractState;
import org.springframework.statemachine.state.ChoicePseudoState;
import org.springframework.statemachine.state.ChoicePseudoState.ChoiceStateData;
import org.springframework.statemachine.state.DefaultPseudoState;
import org.springframework.statemachine.state.EntryPseudoState;
import org.springframework.statemachine.state.ExitPseudoState;
import org.springframework.statemachine.state.ForkPseudoState;
import org.springframework.statemachine.state.HistoryPseudoState;
import org.springframework.statemachine.state.JoinPseudoState;
import org.springframework.statemachine.state.JoinPseudoState.JoinStateData;
import org.springframework.statemachine.state.JunctionPseudoState;
import org.springframework.statemachine.state.JunctionPseudoState.JunctionStateData;
import org.springframework.statemachine.state.PseudoState;
import org.springframework.statemachine.state.PseudoStateKind;
import org.springframework.statemachine.state.RegionState;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.state.StateHolder;
import org.springframework.statemachine.state.StateMachineState;
import org.springframework.statemachine.state.ChoicePseudoState.ChoiceStateData;
import org.springframework.statemachine.state.JoinPseudoState.JoinStateData;
import org.springframework.statemachine.state.JunctionPseudoState.JunctionStateData;
import org.springframework.statemachine.support.DefaultExtendedState;
import org.springframework.statemachine.support.LifecycleObjectSupport;
import org.springframework.statemachine.support.tree.Tree;
import org.springframework.statemachine.support.tree.Tree.Node;
import org.springframework.statemachine.support.tree.TreeTraverser;
import org.springframework.statemachine.support.tree.Tree.Node;
import org.springframework.statemachine.transition.DefaultExternalTransition;
import org.springframework.statemachine.transition.DefaultInternalTransition;
import org.springframework.statemachine.transition.InitialTransition;
@@ -77,15 +87,6 @@ import org.springframework.statemachine.trigger.Trigger;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;
/**
* Base {@link StateMachineFactory} implementation building {@link StateMachine}s.
*
@@ -124,12 +125,28 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
@Override
public StateMachine<S, E> getStateMachine() {
return getStateMachine(null);
return getStateMachine(null, null);
}
@SuppressWarnings("unchecked")
@Override
public StateMachine<S, E> getStateMachine(String machineId) {
return getStateMachine(null, machineId);
}
@Override
public StateMachine<S, E> getStateMachine(UUID uuid) {
return getStateMachine(uuid, null);
}
/**
* Main constructor that create a {@link StateMachine}.
*
* @param uuid for internal usage. Can be null, in that case a random one will be generated.
* @param machineId represent a user Id, up to you to set what you want.
* @return a {@link StateMachine}
*/
@SuppressWarnings("unchecked")
public StateMachine<S, E> getStateMachine(UUID uuid, String machineId) {
if (stateMachineModel.getConfigurationData().isVerifierEnabled()) {
StateMachineModelVerifier<S, E> verifier = stateMachineModel.getConfigurationData().getVerifier();
if (verifier == null) {
@@ -189,7 +206,7 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
for (Collection<StateData<S, E>> regionStateDatas : regionsStateDatas) {
machine = buildMachine(machineMap, stateMap, holderMap, regionStateDatas, transitionsData, resolveBeanFactory(),
contextEvents, defaultExtendedState, stateMachineModel.getTransitionsData(), resolveTaskExecutor(),
resolveTaskScheduler(), machineId);
resolveTaskScheduler(), machineId, null);
regionStack.push(new MachineStackItem<S, E>(machine));
}
@@ -211,13 +228,14 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
StateMachine<S, E> m = buildStateMachineInternal(states, new ArrayList<Transition<S, E>>(), rstate, initialTransition,
null, defaultExtendedState, null, contextEvents, resolveBeanFactory(), resolveTaskExecutor(),
resolveTaskScheduler(), beanName,
machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId());
machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId(),
uuid);
machine = m;
}
} else {
machine = buildMachine(machineMap, stateMap, holderMap, stateDatas, transitionsData, resolveBeanFactory(), contextEvents,
defaultExtendedState, stateMachineModel.getTransitionsData(), resolveTaskExecutor(), resolveTaskScheduler(),
machineId);
machineId, uuid);
if (peek.isInitial() || (!peek.isInitial() && !machineMap.containsKey(peek.getParent()))) {
machineMap.put(peek.getParent(), machine);
}
@@ -418,7 +436,8 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
private StateMachine<S, E> buildMachine(Map<Object, StateMachine<S, E>> machineMap, Map<S, State<S, E>> stateMap,
Map<S, StateHolder<S, E>> holderMap, Collection<StateData<S, E>> stateDatas, Collection<TransitionData<S, E>> transitionsData,
BeanFactory beanFactory, Boolean contextEvents, DefaultExtendedState defaultExtendedState,
TransitionsData<S, E> stateMachineTransitions, TaskExecutor taskExecutor, TaskScheduler taskScheduler, String machineId) {
TransitionsData<S, E> stateMachineTransitions, TaskExecutor taskExecutor, TaskScheduler taskScheduler, String machineId,
UUID uuid) {
State<S, E> state = null;
State<S, E> initialState = null;
PseudoState<S, E> historyState = null;
@@ -725,15 +744,22 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
Transition<S, E> initialTransition = new InitialTransition<S, E>(initialState, initialAction);
StateMachine<S, E> machine = buildStateMachineInternal(states, transitions, initialState, initialTransition,
null, defaultExtendedState, historyState, contextEvents, beanFactory, taskExecutor, taskScheduler,
beanName, machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId());
beanName, machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId(), uuid);
return machine;
}
protected abstract StateMachine<S, E> buildStateMachineInternal(Collection<State<S, E>> states,
Collection<Transition<S, E>> transitions, State<S, E> initialState, Transition<S, E> initialTransition,
Message<E> initialEvent, ExtendedState extendedState, PseudoState<S, E> historyState,
Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor,
TaskScheduler taskScheduler, String beanName, String machineId);
Collection<Transition<S, E>> transitions,
State<S, E> initialState, Transition<S, E> initialTransition,
Message<E> initialEvent, ExtendedState extendedState,
PseudoState<S, E> historyState,
Boolean contextEventsEnabled,
BeanFactory beanFactory,
TaskExecutor taskExecutor,
TaskScheduler taskScheduler,
String beanName,
String machineId,
UUID uuid);
protected abstract State<S, E> buildStateInternal(S id, Collection<E> deferred,
Collection<? extends Action<S, E>> entryActions, Collection<? extends Action<S, E>> exitActions,

View File

@@ -16,6 +16,7 @@
package org.springframework.statemachine.config;
import java.util.Collection;
import java.util.UUID;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNameAware;
@@ -56,12 +57,12 @@ public class ObjectStateMachineFactory<S, E> extends AbstractStateMachineFactory
@Override
protected StateMachine<S, E> buildStateMachineInternal(Collection<State<S, E>> states,
Collection<Transition<S, E>> transitions, State<S, E> initialState, Transition<S, E> initialTransition,
Message<E> initialEvent, ExtendedState extendedState, PseudoState<S, E> historyState,
Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor,
TaskScheduler taskScheduler, String beanName, String machineId) {
Collection<Transition<S, E>> transitions, State<S, E> initialState, Transition<S, E> initialTransition,
Message<E> initialEvent, ExtendedState extendedState, PseudoState<S, E> historyState,
Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor,
TaskScheduler taskScheduler, String beanName, String machineId, UUID uuid) {
ObjectStateMachine<S, E> machine = new ObjectStateMachine<S, E>(states, transitions, initialState, initialTransition, initialEvent,
extendedState);
extendedState, uuid);
machine.setId(machineId);
machine.setHistoryState(historyState);
if (contextEventsEnabled != null) {

View File

@@ -17,6 +17,8 @@ package org.springframework.statemachine.config;
import org.springframework.statemachine.StateMachine;
import java.util.UUID;
/**
* {@code StateMachineFactory} is a strategy interface building {@link StateMachine}s.
*
@@ -42,4 +44,13 @@ public interface StateMachineFactory<S, E> {
* @return a new state machine instance.
*/
StateMachine<S, E> getStateMachine(String machineId);
/**
* Build a new {@link StateMachine} instance
* with a given machine uuid.
*
* @param uuid to be used internally
* @return a new state machine instance.
*/
StateMachine<S, E> getStateMachine(UUID uuid);
}

View File

@@ -15,14 +15,6 @@
*/
package org.springframework.statemachine.support;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
@@ -59,6 +51,14 @@ import org.springframework.statemachine.trigger.Trigger;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Base implementation of a {@link StateMachine} loosely modelled from UML state
* machine.
@@ -104,7 +104,7 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
private Boolean initialEnabled = null;
private UUID uuid = UUID.randomUUID();
private final UUID uuid;
private String id;
@@ -134,7 +134,7 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
*/
public AbstractStateMachine(Collection<State<S, E>> states, Collection<Transition<S, E>> transitions,
State<S, E> initialState, ExtendedState extendedState) {
this(states, transitions, initialState, null, null, extendedState);
this(states, transitions, initialState, null, null, extendedState, null);
}
/**
@@ -146,10 +146,13 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
* @param initialTransition the initial transition
* @param initialEvent the initial event of this machine
* @param extendedState the extended state of this machine
* @param uuid the given uuid for this machine
*/
public AbstractStateMachine(Collection<State<S, E>> states, Collection<Transition<S, E>> transitions,
State<S, E> initialState, Transition<S, E> initialTransition, Message<E> initialEvent, ExtendedState extendedState) {
State<S, E> initialState, Transition<S, E> initialTransition, Message<E> initialEvent,
ExtendedState extendedState, UUID uuid) {
super();
this.uuid = uuid == null ? UUID.randomUUID() : uuid;
this.states = states;
this.transitions = transitions;
this.initialState = initialState;
@@ -185,10 +188,16 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
return extendedState;
}
/**
* @param history to set internal history state.
*/
public void setHistoryState(PseudoState<S, E> history) {
this.history = history;
}
/**
* @return history state attribute.
*/
public PseudoState<S, E> getHistoryState() {
return history;
}

View File

@@ -15,19 +15,6 @@
*/
package org.springframework.statemachine;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -53,6 +40,19 @@ import org.springframework.statemachine.transition.InitialTransition;
import org.springframework.statemachine.transition.Transition;
import org.springframework.statemachine.trigger.EventTrigger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Statemachine tests using regions.
*
@@ -106,7 +106,7 @@ public class RegionMachineTests extends AbstractStateMachineTests {
SyncTaskExecutor taskExecutor = new SyncTaskExecutor();
BeanFactory beanFactory = new DefaultListableBeanFactory();
Transition<TestStates,TestEvents> initialTransition = new InitialTransition<TestStates,TestEvents>(stateSI);
ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateSI, initialTransition, null, null);
ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateSI, initialTransition, null, null, null);
machine.setTaskExecutor(taskExecutor);
machine.setBeanFactory(beanFactory);
machine.afterPropertiesSet();
@@ -172,7 +172,7 @@ public class RegionMachineTests extends AbstractStateMachineTests {
new DefaultExternalTransition<TestStates,TestEvents>(stateS111, stateS112, null, TestEvents.E2, null, new EventTrigger<TestStates,TestEvents>(TestEvents.E2));
transitions11.add(transitionFromS111ToS112);
Transition<TestStates,TestEvents> initialTransition11 = new InitialTransition<TestStates,TestEvents>(stateS111);
ObjectStateMachine<TestStates, TestEvents> machine11 = new ObjectStateMachine<TestStates, TestEvents>(states11, transitions11, stateS111, initialTransition11, null, null);
ObjectStateMachine<TestStates, TestEvents> machine11 = new ObjectStateMachine<TestStates, TestEvents>(states11, transitions11, stateS111, initialTransition11, null, null, null);
machine11.setTaskExecutor(taskExecutor);
machine11.setBeanFactory(beanFactory);
machine11.afterPropertiesSet();
@@ -185,7 +185,7 @@ public class RegionMachineTests extends AbstractStateMachineTests {
new DefaultExternalTransition<TestStates,TestEvents>(stateSI, stateS111, null, TestEvents.E3, null, new EventTrigger<TestStates,TestEvents>(TestEvents.E3));
transitions12.add(transitionFromSIToS121);
Transition<TestStates,TestEvents> initialTransition12 = new InitialTransition<TestStates,TestEvents>(stateS121);
ObjectStateMachine<TestStates, TestEvents> machine12 = new ObjectStateMachine<TestStates, TestEvents>(states12, transitions12, stateS121, initialTransition12, null, null);
ObjectStateMachine<TestStates, TestEvents> machine12 = new ObjectStateMachine<TestStates, TestEvents>(states12, transitions12, stateS121, initialTransition12, null, null, null);
machine12.setTaskExecutor(taskExecutor);
machine12.setBeanFactory(beanFactory);
machine12.afterPropertiesSet();
@@ -202,7 +202,7 @@ public class RegionMachineTests extends AbstractStateMachineTests {
new DefaultExternalTransition<TestStates,TestEvents>(stateSI, stateR, null, TestEvents.E1, null, new EventTrigger<TestStates,TestEvents>(TestEvents.E1));
transitions.add(transitionFromSIToRegionstate);
Transition<TestStates,TestEvents> initialTransition = new InitialTransition<TestStates,TestEvents>(stateR);
ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateR, initialTransition, null, null);
ObjectStateMachine<TestStates, TestEvents> machine = new ObjectStateMachine<TestStates, TestEvents>(states, transitions, stateR, initialTransition, null, null, null);
machine.setTaskExecutor(taskExecutor);
machine.setBeanFactory(beanFactory);