From e6f10b60f55a85482f46e55f7801636c680b7859 Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 23 Aug 2016 15:37:38 +0200 Subject: [PATCH] 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 --- .../statemachine/ObjectStateMachine.java | 10 ++- .../config/AbstractStateMachineFactory.java | 74 +++++++++++++------ .../config/ObjectStateMachineFactory.java | 11 +-- .../config/StateMachineFactory.java | 11 +++ .../support/AbstractStateMachine.java | 31 +++++--- .../statemachine/RegionMachineTests.java | 34 ++++----- 6 files changed, 110 insertions(+), 61 deletions(-) diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/ObjectStateMachine.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/ObjectStateMachine.java index 0ec9314d..55f0ad95 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/ObjectStateMachine.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/ObjectStateMachine.java @@ -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 extends AbstractStateMachine { * @param initialTransition the initial transition * @param initialEvent the initial event * @param extendedState the extended state + * @param uuid the given uuid. */ public ObjectStateMachine(Collection> states, Collection> transitions, State initialState, Transition initialTransition, - Message initialEvent, ExtendedState extendedState) { - super(states, transitions, initialState, initialTransition, initialEvent, extendedState); + Message initialEvent, ExtendedState extendedState, UUID uuid) { + super(states, transitions, initialState, initialTransition, initialEvent, extendedState, uuid); } } diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/AbstractStateMachineFactory.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/AbstractStateMachineFactory.java index 885fe327..31fd7ece 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/AbstractStateMachineFactory.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/AbstractStateMachineFactory.java @@ -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 extends LifecycleObjectS @Override public StateMachine getStateMachine() { - return getStateMachine(null); + return getStateMachine(null, null); } - @SuppressWarnings("unchecked") @Override public StateMachine getStateMachine(String machineId) { + return getStateMachine(null, machineId); + } + + @Override + public StateMachine 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 getStateMachine(UUID uuid, String machineId) { if (stateMachineModel.getConfigurationData().isVerifierEnabled()) { StateMachineModelVerifier verifier = stateMachineModel.getConfigurationData().getVerifier(); if (verifier == null) { @@ -189,7 +206,7 @@ public abstract class AbstractStateMachineFactory extends LifecycleObjectS for (Collection> regionStateDatas : regionsStateDatas) { machine = buildMachine(machineMap, stateMap, holderMap, regionStateDatas, transitionsData, resolveBeanFactory(), contextEvents, defaultExtendedState, stateMachineModel.getTransitionsData(), resolveTaskExecutor(), - resolveTaskScheduler(), machineId); + resolveTaskScheduler(), machineId, null); regionStack.push(new MachineStackItem(machine)); } @@ -211,13 +228,14 @@ public abstract class AbstractStateMachineFactory extends LifecycleObjectS StateMachine m = buildStateMachineInternal(states, new ArrayList>(), 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 extends LifecycleObjectS private StateMachine buildMachine(Map> machineMap, Map> stateMap, Map> holderMap, Collection> stateDatas, Collection> transitionsData, BeanFactory beanFactory, Boolean contextEvents, DefaultExtendedState defaultExtendedState, - TransitionsData stateMachineTransitions, TaskExecutor taskExecutor, TaskScheduler taskScheduler, String machineId) { + TransitionsData stateMachineTransitions, TaskExecutor taskExecutor, TaskScheduler taskScheduler, String machineId, + UUID uuid) { State state = null; State initialState = null; PseudoState historyState = null; @@ -725,15 +744,22 @@ public abstract class AbstractStateMachineFactory extends LifecycleObjectS Transition initialTransition = new InitialTransition(initialState, initialAction); StateMachine 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 buildStateMachineInternal(Collection> states, - Collection> transitions, State initialState, Transition initialTransition, - Message initialEvent, ExtendedState extendedState, PseudoState historyState, - Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor, - TaskScheduler taskScheduler, String beanName, String machineId); + Collection> transitions, + State initialState, Transition initialTransition, + Message initialEvent, ExtendedState extendedState, + PseudoState historyState, + Boolean contextEventsEnabled, + BeanFactory beanFactory, + TaskExecutor taskExecutor, + TaskScheduler taskScheduler, + String beanName, + String machineId, + UUID uuid); protected abstract State buildStateInternal(S id, Collection deferred, Collection> entryActions, Collection> exitActions, diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/ObjectStateMachineFactory.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/ObjectStateMachineFactory.java index 8ac2fbcc..8cfd14ed 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/ObjectStateMachineFactory.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/ObjectStateMachineFactory.java @@ -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 extends AbstractStateMachineFactory @Override protected StateMachine buildStateMachineInternal(Collection> states, - Collection> transitions, State initialState, Transition initialTransition, - Message initialEvent, ExtendedState extendedState, PseudoState historyState, - Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor, - TaskScheduler taskScheduler, String beanName, String machineId) { + Collection> transitions, State initialState, Transition initialTransition, + Message initialEvent, ExtendedState extendedState, PseudoState historyState, + Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor, + TaskScheduler taskScheduler, String beanName, String machineId, UUID uuid) { ObjectStateMachine machine = new ObjectStateMachine(states, transitions, initialState, initialTransition, initialEvent, - extendedState); + extendedState, uuid); machine.setId(machineId); machine.setHistoryState(historyState); if (contextEventsEnabled != null) { diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/StateMachineFactory.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/StateMachineFactory.java index 32f30b8c..325ff18b 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/StateMachineFactory.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/StateMachineFactory.java @@ -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 { * @return a new state machine instance. */ StateMachine 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 getStateMachine(UUID uuid); } diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java index 3333a35c..1d2d0d9f 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java @@ -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 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 extends StateMachineObjectSuppo */ public AbstractStateMachine(Collection> states, Collection> transitions, State 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 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> states, Collection> transitions, - State initialState, Transition initialTransition, Message initialEvent, ExtendedState extendedState) { + State initialState, Transition initialTransition, Message 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 extends StateMachineObjectSuppo return extendedState; } + /** + * @param history to set internal history state. + */ public void setHistoryState(PseudoState history) { this.history = history; } + /** + * @return history state attribute. + */ public PseudoState getHistoryState() { return history; } diff --git a/spring-statemachine-core/src/test/java/org/springframework/statemachine/RegionMachineTests.java b/spring-statemachine-core/src/test/java/org/springframework/statemachine/RegionMachineTests.java index 6d9a6484..8fd18321 100644 --- a/spring-statemachine-core/src/test/java/org/springframework/statemachine/RegionMachineTests.java +++ b/spring-statemachine-core/src/test/java/org/springframework/statemachine/RegionMachineTests.java @@ -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 initialTransition = new InitialTransition(stateSI); - ObjectStateMachine machine = new ObjectStateMachine(states, transitions, stateSI, initialTransition, null, null); + ObjectStateMachine machine = new ObjectStateMachine(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(stateS111, stateS112, null, TestEvents.E2, null, new EventTrigger(TestEvents.E2)); transitions11.add(transitionFromS111ToS112); Transition initialTransition11 = new InitialTransition(stateS111); - ObjectStateMachine machine11 = new ObjectStateMachine(states11, transitions11, stateS111, initialTransition11, null, null); + ObjectStateMachine machine11 = new ObjectStateMachine(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(stateSI, stateS111, null, TestEvents.E3, null, new EventTrigger(TestEvents.E3)); transitions12.add(transitionFromSIToS121); Transition initialTransition12 = new InitialTransition(stateS121); - ObjectStateMachine machine12 = new ObjectStateMachine(states12, transitions12, stateS121, initialTransition12, null, null); + ObjectStateMachine machine12 = new ObjectStateMachine(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(stateSI, stateR, null, TestEvents.E1, null, new EventTrigger(TestEvents.E1)); transitions.add(transitionFromSIToRegionstate); Transition initialTransition = new InitialTransition(stateR); - ObjectStateMachine machine = new ObjectStateMachine(states, transitions, stateR, initialTransition, null, null); + ObjectStateMachine machine = new ObjectStateMachine(states, transitions, stateR, initialTransition, null, null, null); machine.setTaskExecutor(taskExecutor); machine.setBeanFactory(beanFactory);