Add builder pattern for state machine instantiation
- Relates to #45 - Modify current annotation builder model to work via manual StateMachineBuilder class. - Add ConfigurationConfigurer to configure bean factory, task executor and task scheduler via builder.
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
package org.springframework.statemachine.config;
|
||||
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
@@ -36,17 +38,23 @@ public abstract class AbstractStateMachineConfigurerAdapter<S, E> implements Sta
|
||||
|
||||
private StateMachineTransitionBuilder<S, E> transitionBuilder;
|
||||
private StateMachineStateBuilder<S, E> stateBuilder;
|
||||
private StateMachineConfigurationBuilder<S, E> configurationBuilder;
|
||||
|
||||
@Override
|
||||
public final void init(StateMachineConfigBuilder<S, E> config) throws Exception {
|
||||
config.setSharedObject(StateMachineTransitionBuilder.class, getStateMachineTransitionBuilder());
|
||||
config.setSharedObject(StateMachineStateBuilder.class, getStateMachineStateBuilder());
|
||||
config.setSharedObject(StateMachineConfigurationBuilder.class, getStateMachineConfigurationBuilder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigBuilder<S, E> config) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<S, E> config) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<S, E> states) throws Exception {
|
||||
}
|
||||
@@ -78,4 +86,13 @@ public abstract class AbstractStateMachineConfigurerAdapter<S, E> implements Sta
|
||||
return stateBuilder;
|
||||
}
|
||||
|
||||
protected final StateMachineConfigurationBuilder<S, E> getStateMachineConfigurationBuilder() throws Exception {
|
||||
if (configurationBuilder != null) {
|
||||
return configurationBuilder;
|
||||
}
|
||||
configurationBuilder = new StateMachineConfigurationBuilder<S, E>(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true);
|
||||
configure(configurationBuilder);
|
||||
return configurationBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,12 +25,15 @@ import java.util.Map.Entry;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.statemachine.ExtendedState;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.access.StateMachineAccess;
|
||||
import org.springframework.statemachine.access.StateMachineFunction;
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStates;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitions;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitions.ChoiceData;
|
||||
@@ -77,16 +80,20 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
|
||||
private final StateMachineStates<S, E> stateMachineStates;
|
||||
|
||||
private final StateMachineConfigurationConfig<S,E> stateMachineConfigurationConfig;
|
||||
|
||||
private Boolean contextEvents;
|
||||
|
||||
/**
|
||||
* Instantiates a new enum state machine factory.
|
||||
*
|
||||
* @param stateMachineConfigurationConfig the state machine generic config
|
||||
* @param stateMachineTransitions the state machine transitions
|
||||
* @param stateMachineStates the state machine states
|
||||
*/
|
||||
public AbstractStateMachineFactory(StateMachineTransitions<S, E> stateMachineTransitions,
|
||||
StateMachineStates<S, E> stateMachineStates) {
|
||||
public AbstractStateMachineFactory(StateMachineConfigurationConfig<S, E> stateMachineConfigurationConfig,
|
||||
StateMachineTransitions<S, E> stateMachineTransitions, StateMachineStates<S, E> stateMachineStates) {
|
||||
this.stateMachineConfigurationConfig = stateMachineConfigurationConfig;
|
||||
this.stateMachineTransitions = stateMachineTransitions;
|
||||
this.stateMachineStates = stateMachineStates;
|
||||
}
|
||||
@@ -144,7 +151,8 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
if (initialCount > 1) {
|
||||
for (Collection<StateData<S, E>> regionStateDatas : regionsStateDatas) {
|
||||
machine = buildMachine(machineMap, stateMap, regionStateDatas, transitionsData, getBeanFactory(),
|
||||
contextEvents, defaultExtendedState, stateMachineTransitions);
|
||||
contextEvents, defaultExtendedState, stateMachineTransitions, getTaskExecutor(),
|
||||
getTaskScheduler());
|
||||
regionStack.push(new MachineStackItem<S, E>(machine));
|
||||
}
|
||||
|
||||
@@ -163,12 +171,13 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
states.add(rstate);
|
||||
Transition<S, E> initialTransition = new InitialTransition<S, E>(rstate);
|
||||
StateMachine<S, E> m = buildStateMachineInternal(states, new ArrayList<Transition<S, E>>(), rstate,
|
||||
initialTransition, null, defaultExtendedState, null, contextEvents, getBeanFactory());
|
||||
initialTransition, null, defaultExtendedState, null, contextEvents, getBeanFactory(),
|
||||
getTaskExecutor(), getTaskScheduler());
|
||||
machine = m;
|
||||
}
|
||||
} else {
|
||||
machine = buildMachine(machineMap, stateMap, stateDatas, transitionsData, getBeanFactory(),
|
||||
contextEvents, defaultExtendedState, stateMachineTransitions);
|
||||
contextEvents, defaultExtendedState, stateMachineTransitions, getTaskExecutor(), getTaskScheduler());
|
||||
if (peek.isInitial() || (!peek.isInitial() && !machineMap.containsKey(peek.getParent()))) {
|
||||
machineMap.put(peek.getParent(), machine);
|
||||
}
|
||||
@@ -281,7 +290,8 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
Map<Object, StateMachine<S, E>> machineMap, Map<S, State<S, E>> stateMap,
|
||||
Collection<StateData<S, E>> stateDatas, Collection<TransitionData<S, E>> transitionsData,
|
||||
BeanFactory beanFactory, Boolean contextEvents, DefaultExtendedState defaultExtendedState,
|
||||
StateMachineTransitions<S, E> stateMachineTransitions) {
|
||||
StateMachineTransitions<S, E> stateMachineTransitions, TaskExecutor taskExecutor,
|
||||
TaskScheduler taskScheduler) {
|
||||
State<S, E> state = null;
|
||||
State<S, E> initialState = null;
|
||||
PseudoState<S, E> historyState = null;
|
||||
@@ -451,13 +461,15 @@ 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);
|
||||
defaultExtendedState, historyState, contextEvents, beanFactory, taskExecutor, taskScheduler);
|
||||
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);
|
||||
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);
|
||||
|
||||
protected abstract State<S, E> buildStateInternal(S id, Collection<E> deferred, Collection<? extends Action<S, E>> entryActions, Collection<? extends Action<S, E>> exitActions,
|
||||
PseudoState<S, E> pseudoState);
|
||||
|
||||
@@ -18,11 +18,14 @@ package org.springframework.statemachine.config;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.statemachine.ObjectStateMachine;
|
||||
import org.springframework.statemachine.ExtendedState;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStates;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitions;
|
||||
import org.springframework.statemachine.state.ObjectState;
|
||||
@@ -41,15 +44,17 @@ import org.springframework.statemachine.transition.Transition;
|
||||
*/
|
||||
public class ObjectStateMachineFactory<S, E> extends AbstractStateMachineFactory<S, E> {
|
||||
|
||||
public ObjectStateMachineFactory(StateMachineTransitions<S, E> stateMachineTransitions,
|
||||
public ObjectStateMachineFactory(StateMachineConfigurationConfig<S,E> stateMachineConfigurationConfig, StateMachineTransitions<S, E> stateMachineTransitions,
|
||||
StateMachineStates<S, E> stateMachineStates) {
|
||||
super(stateMachineTransitions, stateMachineStates);
|
||||
super(stateMachineConfigurationConfig, stateMachineTransitions, stateMachineStates);
|
||||
}
|
||||
|
||||
@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) {
|
||||
Message<E> initialEvent, ExtendedState extendedState, PseudoState<S, E> historyState,
|
||||
Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor,
|
||||
TaskScheduler taskScheduler) {
|
||||
ObjectStateMachine<S, E> machine = new ObjectStateMachine<S, E>(states, transitions, initialState, initialTransition, initialEvent,
|
||||
extendedState);
|
||||
machine.setHistoryState(historyState);
|
||||
@@ -59,6 +64,12 @@ public class ObjectStateMachineFactory<S, E> extends AbstractStateMachineFactory
|
||||
if (beanFactory != null) {
|
||||
machine.setBeanFactory(beanFactory);
|
||||
}
|
||||
if (taskExecutor != null) {
|
||||
machine.setTaskExecutor(taskExecutor);
|
||||
}
|
||||
if (taskScheduler != null) {
|
||||
machine.setTaskScheduler(taskScheduler);;
|
||||
}
|
||||
machine.afterPropertiesSet();
|
||||
return machine;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.config;
|
||||
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.StateMachineException;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStates;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitions;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationBuilder;
|
||||
import org.springframework.statemachine.config.common.annotation.ObjectPostProcessor;
|
||||
|
||||
/**
|
||||
* {@code StateMachineBuilder} provides a builder pattern for
|
||||
* {@link StateMachine} using a similar concepts found from a
|
||||
* normal annotation based configuration.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
*/
|
||||
public class StateMachineBuilder {
|
||||
|
||||
/**
|
||||
* Gets a builder for a {@link StateMachine}.
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
* @return the builder
|
||||
*/
|
||||
public static <S, E> Builder<S, E> builder() {
|
||||
return new Builder<S, E>();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code Builder} implementation handling logic of building
|
||||
* a {@link StateMachine} manually.
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public static class Builder<S, E> {
|
||||
|
||||
private StateMachineConfigBuilder<S, E> builder;
|
||||
private BuilderStateMachineConfigurerAdapter<S, E> adapter;
|
||||
|
||||
/**
|
||||
* Instantiates a new builder.
|
||||
*/
|
||||
public Builder() {
|
||||
adapter = new BuilderStateMachineConfigurerAdapter<S, E>();
|
||||
builder = new StateMachineConfigBuilder<S, E>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure configuration.
|
||||
*
|
||||
* @return the state machine configuration configurer
|
||||
*/
|
||||
public StateMachineConfigurationConfigurer<S, E> configureConfiguration() {
|
||||
return adapter.configurationBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure states.
|
||||
*
|
||||
* @return the state machine state configurer
|
||||
*/
|
||||
public StateMachineStateConfigurer<S, E> configureStates() {
|
||||
return adapter.stateBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure transitions.
|
||||
*
|
||||
* @return the state machine transition configurer
|
||||
*/
|
||||
public StateMachineTransitionConfigurer<S, E> configureTransitions() {
|
||||
return adapter.transitionBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link StateMachine}.
|
||||
*
|
||||
* @return the state machine
|
||||
*/
|
||||
public StateMachine<S, E> build() {
|
||||
try {
|
||||
builder.apply(adapter);
|
||||
StateMachineConfig<S, E> stateMachineConfig = builder.getOrBuild();
|
||||
|
||||
StateMachineTransitions<S, E> stateMachineTransitions = stateMachineConfig.getTransitions();
|
||||
StateMachineStates<S, E> stateMachineStates = stateMachineConfig.getStates();
|
||||
StateMachineConfigurationConfig<S, E> stateMachineConfigurationConfig = stateMachineConfig.getStateMachineConfigurationConfig();
|
||||
ObjectStateMachineFactory<S, E> stateMachineFactory = new ObjectStateMachineFactory<S, E>(
|
||||
stateMachineConfigurationConfig, stateMachineTransitions, stateMachineStates);
|
||||
|
||||
if (stateMachineConfigurationConfig.getBeanFactory() != null) {
|
||||
stateMachineFactory.setBeanFactory(stateMachineConfigurationConfig.getBeanFactory());
|
||||
}
|
||||
if (stateMachineConfigurationConfig.getTaskExecutor() != null) {
|
||||
stateMachineFactory.setTaskExecutor(stateMachineConfigurationConfig.getTaskExecutor());
|
||||
}
|
||||
if (stateMachineConfigurationConfig.getTaskScheculer() != null) {
|
||||
stateMachineFactory.setTaskScheduler(stateMachineConfigurationConfig.getTaskScheculer());
|
||||
}
|
||||
|
||||
return stateMachineFactory.getStateMachine();
|
||||
} catch (Exception e) {
|
||||
throw new StateMachineException("Error building state machine", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class BuilderStateMachineConfigurerAdapter<S extends Object, E extends Object>
|
||||
implements StateMachineConfigurer<S, E> {
|
||||
|
||||
private StateMachineTransitionBuilder<S, E> transitionBuilder;
|
||||
private StateMachineStateBuilder<S, E> stateBuilder;
|
||||
private StateMachineConfigurationBuilder<S, E> configurationBuilder;
|
||||
|
||||
BuilderStateMachineConfigurerAdapter() {
|
||||
try {
|
||||
getStateMachineTransitionBuilder();
|
||||
getStateMachineStateBuilder();
|
||||
getStateMachineConfigurationBuilder();
|
||||
} catch (Exception e) {
|
||||
throw new StateMachineException("Error instantiating builder adapter", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(StateMachineConfigBuilder<S, E> config) throws Exception {
|
||||
config.setSharedObject(StateMachineTransitionBuilder.class, getStateMachineTransitionBuilder());
|
||||
config.setSharedObject(StateMachineStateBuilder.class, getStateMachineStateBuilder());
|
||||
config.setSharedObject(StateMachineConfigurationBuilder.class, getStateMachineConfigurationBuilder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigBuilder<S, E> builder) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssignable(AnnotationBuilder<StateMachineConfig<S, E>> builder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<S, E> config) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<S, E> states) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<S, E> transitions) throws Exception {
|
||||
}
|
||||
|
||||
protected final StateMachineTransitionBuilder<S, E> getStateMachineTransitionBuilder() throws Exception {
|
||||
if (transitionBuilder != null) {
|
||||
return transitionBuilder;
|
||||
}
|
||||
transitionBuilder = new StateMachineTransitionBuilder<S, E>(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true);
|
||||
return transitionBuilder;
|
||||
}
|
||||
|
||||
protected final StateMachineStateBuilder<S, E> getStateMachineStateBuilder() throws Exception {
|
||||
if (stateBuilder != null) {
|
||||
return stateBuilder;
|
||||
}
|
||||
stateBuilder = new StateMachineStateBuilder<S, E>(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true);
|
||||
return stateBuilder;
|
||||
}
|
||||
|
||||
protected final StateMachineConfigurationBuilder<S, E> getStateMachineConfigurationBuilder() throws Exception {
|
||||
if (configurationBuilder != null) {
|
||||
return configurationBuilder;
|
||||
}
|
||||
configurationBuilder = new StateMachineConfigurationBuilder<S, E>(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true);
|
||||
return configurationBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,20 +15,28 @@
|
||||
*/
|
||||
package org.springframework.statemachine.config;
|
||||
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStates;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitions;
|
||||
|
||||
public class StateMachineConfig<S, E> {
|
||||
|
||||
public final StateMachineConfigurationConfig<S, E> stateMachineConfigurationConfig;
|
||||
|
||||
public final StateMachineTransitions<S, E> transitions;
|
||||
|
||||
public final StateMachineStates<S, E> states;
|
||||
|
||||
public StateMachineConfig(StateMachineTransitions<S, E> transitions, StateMachineStates<S, E> states) {
|
||||
public StateMachineConfig(StateMachineConfigurationConfig<S, E> stateMachineConfigurationConfig, StateMachineTransitions<S, E> transitions, StateMachineStates<S, E> states) {
|
||||
this.stateMachineConfigurationConfig = stateMachineConfigurationConfig;
|
||||
this.transitions = transitions;
|
||||
this.states = states;
|
||||
}
|
||||
|
||||
public StateMachineConfigurationConfig<S, E> getStateMachineConfigurationConfig() {
|
||||
return stateMachineConfigurationConfig;
|
||||
}
|
||||
|
||||
public StateMachineTransitions<S, E> getTransitions() {
|
||||
return transitions;
|
||||
}
|
||||
@@ -36,4 +44,5 @@ public class StateMachineConfig<S, E> {
|
||||
public StateMachineStates<S, E> getStates() {
|
||||
return states;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,9 +27,11 @@ public class StateMachineConfigBuilder<S, E>
|
||||
protected StateMachineConfig<S, E> performBuild() throws Exception {
|
||||
StateMachineTransitionBuilder<?, ?> sharedObject = getSharedObject(StateMachineTransitionBuilder.class);
|
||||
StateMachineStateBuilder<?, ?> sharedObject2 = getSharedObject(StateMachineStateBuilder.class);
|
||||
StateMachineStates<S, E> states = (StateMachineStates<S, E>) sharedObject2.build();
|
||||
StateMachineConfigurationBuilder<?, ?> sharedObject3 = getSharedObject(StateMachineConfigurationBuilder.class);
|
||||
StateMachineTransitions<S, E> transitions = (StateMachineTransitions<S, E>) sharedObject.build();
|
||||
StateMachineConfig<S, E> bean = new StateMachineConfig<S, E>(transitions, states);
|
||||
StateMachineStates<S, E> states = (StateMachineStates<S, E>) sharedObject2.build();
|
||||
StateMachineConfigurationConfig<S, E> config = (StateMachineConfigurationConfig<S, E>) sharedObject3.build();
|
||||
StateMachineConfig<S, E> bean = new StateMachineConfig<S, E>(config, transitions, states);
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.config.builders;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.statemachine.config.common.annotation.AbstractConfiguredAnnotationBuilder;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationBuilder;
|
||||
import org.springframework.statemachine.config.common.annotation.ObjectPostProcessor;
|
||||
import org.springframework.statemachine.config.configurers.ConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.DefaultConfigurationConfigurer;
|
||||
|
||||
/**
|
||||
* {@link AnnotationBuilder} for {@link StateMachineStates}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public class StateMachineConfigurationBuilder<S, E>
|
||||
extends AbstractConfiguredAnnotationBuilder<StateMachineConfigurationConfig<S, E>, StateMachineConfigurationConfigurer<S, E>, StateMachineConfigurationBuilder<S, E>>
|
||||
implements StateMachineConfigurationConfigurer<S, E> {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private TaskExecutor taskExecutor;
|
||||
private TaskScheduler taskScheculer;
|
||||
|
||||
public StateMachineConfigurationBuilder() {
|
||||
super();
|
||||
}
|
||||
|
||||
public StateMachineConfigurationBuilder(ObjectPostProcessor<Object> objectPostProcessor,
|
||||
boolean allowConfigurersOfSameType) {
|
||||
super(objectPostProcessor, allowConfigurersOfSameType);
|
||||
}
|
||||
|
||||
public StateMachineConfigurationBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
super(objectPostProcessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationConfigurer<S, E> withConfiguration() throws Exception {
|
||||
return apply(new DefaultConfigurationConfigurer<S, E>());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StateMachineConfigurationConfig<S, E> performBuild() throws Exception {
|
||||
return new StateMachineConfigurationConfig<>(beanFactory, taskExecutor, taskScheculer);
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public void setTaskExecutor(TaskExecutor taskExecutor) {
|
||||
this.taskExecutor = taskExecutor;
|
||||
}
|
||||
|
||||
public void setTaskScheculer(TaskScheduler taskScheculer) {
|
||||
this.taskScheculer = taskScheculer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.config.builders;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
|
||||
public class StateMachineConfigurationConfig<S, E> {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
private final TaskExecutor taskExecutor;
|
||||
private final TaskScheduler taskScheculer;
|
||||
|
||||
public StateMachineConfigurationConfig(BeanFactory beanFactory, TaskExecutor taskExecutor,
|
||||
TaskScheduler taskScheculer) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.taskExecutor = taskExecutor;
|
||||
this.taskScheculer = taskScheculer;
|
||||
}
|
||||
|
||||
public BeanFactory getBeanFactory() {
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
public TaskExecutor getTaskExecutor() {
|
||||
return taskExecutor;
|
||||
}
|
||||
|
||||
public TaskScheduler getTaskScheculer() {
|
||||
return taskScheculer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.config.builders;
|
||||
|
||||
import org.springframework.statemachine.config.configurers.ConfigurationConfigurer;
|
||||
|
||||
/**
|
||||
* Configurer interface exposing generic config.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public interface StateMachineConfigurationConfigurer<S, E> {
|
||||
|
||||
/**
|
||||
* Gets a configurer for generic config.
|
||||
*
|
||||
* @return {@link ConfigurationConfigurer} for chaining
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
ConfigurationConfigurer<S, E> withConfiguration() throws Exception;
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import org.springframework.statemachine.config.common.annotation.AnnotationConfi
|
||||
|
||||
/**
|
||||
* {@link AnnotationConfigurer} exposing configurers for states and transitions.
|
||||
*
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
@@ -29,9 +29,17 @@ import org.springframework.statemachine.config.common.annotation.AnnotationConfi
|
||||
public interface StateMachineConfigurer<S, E> extends
|
||||
AnnotationConfigurer<StateMachineConfig<S, E>, StateMachineConfigBuilder<S, E>> {
|
||||
|
||||
/**
|
||||
* Callback for {@link StateMachineConfigurationConfigurer}.
|
||||
*
|
||||
* @param config the {@link StateMachineConfigurationConfigurer}
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
void configure(StateMachineConfigurationConfigurer<S, E> config) throws Exception;
|
||||
|
||||
/**
|
||||
* Callback for {@link StateMachineStateConfigurer}.
|
||||
*
|
||||
*
|
||||
* @param states the {@link StateMachineStateConfigurer}
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
@@ -39,7 +47,7 @@ public interface StateMachineConfigurer<S, E> extends
|
||||
|
||||
/**
|
||||
* Callback for {@link StateMachineTransitionConfigurer}.
|
||||
*
|
||||
*
|
||||
* @param transitions the {@link StateMachineTransitionConfigurer}
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.statemachine.config.EnableStateMachine;
|
||||
import org.springframework.statemachine.config.ObjectStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStates;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitions;
|
||||
import org.springframework.statemachine.config.common.annotation.AbstractImportingAnnotationConfiguration;
|
||||
@@ -88,8 +89,9 @@ public class StateMachineConfiguration<S extends Enum<S>, E extends Enum<E>> ext
|
||||
StateMachineConfig<S, E> stateMachineConfig = getBuilder().getOrBuild();
|
||||
StateMachineTransitions<S, E> stateMachineTransitions = stateMachineConfig.getTransitions();
|
||||
StateMachineStates<S, E> stateMachineStates = stateMachineConfig.getStates();
|
||||
StateMachineConfigurationConfig<S, E> stateMachineConfigurationConfig = stateMachineConfig.getStateMachineConfigurationConfig();
|
||||
ObjectStateMachineFactory<S, E> stateMachineFactory = new ObjectStateMachineFactory<S, E>(
|
||||
stateMachineTransitions, stateMachineStates);
|
||||
stateMachineConfigurationConfig, stateMachineTransitions, stateMachineStates);
|
||||
stateMachineFactory.setBeanFactory(getBeanFactory());
|
||||
stateMachineFactory.setContextEventsEnabled(contextEvents);
|
||||
setObject(stateMachineFactory.getStateMachine());
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.statemachine.config.ObjectStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfig;
|
||||
import org.springframework.statemachine.config.StateMachineFactory;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStates;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitions;
|
||||
import org.springframework.statemachine.config.common.annotation.AbstractImportingAnnotationConfiguration;
|
||||
@@ -109,7 +110,8 @@ public class StateMachineFactoryConfiguration<S extends Enum<S>, E extends Enum<
|
||||
StateMachineConfig<S, E> stateMachineConfig = builder.getOrBuild();
|
||||
StateMachineTransitions<S, E> stateMachineTransitions = stateMachineConfig.getTransitions();
|
||||
StateMachineStates<S, E> stateMachineStates = stateMachineConfig.getStates();
|
||||
ObjectStateMachineFactory<S,E> enumStateMachineFactory = new ObjectStateMachineFactory<S, E>(stateMachineTransitions, stateMachineStates);
|
||||
StateMachineConfigurationConfig<S, E> stateMachineConfigurationConfig = stateMachineConfig.getStateMachineConfigurationConfig();
|
||||
ObjectStateMachineFactory<S,E> enumStateMachineFactory = new ObjectStateMachineFactory<S, E>(stateMachineConfigurationConfig, stateMachineTransitions, stateMachineStates);
|
||||
enumStateMachineFactory.setBeanFactory(beanFactory);
|
||||
enumStateMachineFactory.setContextEventsEnabled(contextEvents);
|
||||
this.stateMachineFactory = enumStateMachineFactory;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.config.configurers;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurerBuilder;
|
||||
|
||||
/**
|
||||
* Base {@code ConfigConfigurer} interface for configuring generic config.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public interface ConfigurationConfigurer<S, E> extends
|
||||
AnnotationConfigurerBuilder<StateMachineConfigurationConfigurer<S, E>> {
|
||||
|
||||
/**
|
||||
* Specify a {@link BeanFactory}.
|
||||
*
|
||||
* @param beanFactory the bean factory
|
||||
* @return configurer for chaining
|
||||
*/
|
||||
ConfigurationConfigurer<S, E> beanFactory(BeanFactory beanFactory);
|
||||
|
||||
/**
|
||||
* Specify a {@link TaskExecutor}.
|
||||
*
|
||||
* @param beanFactory the bean factory
|
||||
* @return configurer for chaining
|
||||
*/
|
||||
ConfigurationConfigurer<S, E> taskExecutor(TaskExecutor taskExecutor);
|
||||
|
||||
/**
|
||||
* Specify a {@link TaskScheduler}.
|
||||
*
|
||||
* @param beanFactory the bean factory
|
||||
* @return configurer for chaining
|
||||
*/
|
||||
ConfigurationConfigurer<S, E> taskScheduler(TaskScheduler taskScheduler);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.config.configurers;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* Default implementation of a {@link ConfigurationConfigurer}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public class DefaultConfigurationConfigurer<S, E>
|
||||
extends AnnotationConfigurerAdapter<StateMachineConfigurationConfig<S, E>, StateMachineConfigurationConfigurer<S, E>, StateMachineConfigurationBuilder<S, E>>
|
||||
implements ConfigurationConfigurer<S, E> {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private TaskExecutor taskExecutor;
|
||||
private TaskScheduler taskScheculer;
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationBuilder<S, E> builder) throws Exception {
|
||||
builder.setBeanFactory(beanFactory);
|
||||
builder.setTaskExecutor(taskExecutor);
|
||||
builder.setTaskScheculer(taskScheculer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationConfigurer<S, E> beanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationConfigurer<S, E> taskExecutor(TaskExecutor taskExecutor) {
|
||||
this.taskExecutor = taskExecutor;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationConfigurer<S, E> taskScheduler(TaskScheduler taskScheduler) {
|
||||
this.taskScheculer = taskScheduler;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.config;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.config.StateMachineBuilder.Builder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStates;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitions;
|
||||
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||
import org.springframework.statemachine.state.State;
|
||||
import org.springframework.statemachine.transition.Transition;
|
||||
|
||||
public class ManualBuilderTests {
|
||||
|
||||
@Test
|
||||
public void testManualBuildConcept() throws Exception {
|
||||
StateMachineConfigBuilder<String, String> builder = new StateMachineConfigBuilder<String, String>();
|
||||
Config config = new Config();
|
||||
builder.apply(config);
|
||||
StateMachineConfig<String, String> stateMachineConfig = builder.getOrBuild();
|
||||
|
||||
StateMachineTransitions<String, String> stateMachineTransitions = stateMachineConfig.getTransitions();
|
||||
StateMachineStates<String, String> stateMachineStates = stateMachineConfig.getStates();
|
||||
StateMachineConfigurationConfig<String, String> stateMachineConfigurationConfig = stateMachineConfig.getStateMachineConfigurationConfig();
|
||||
ObjectStateMachineFactory<String, String> stateMachineFactory = new ObjectStateMachineFactory<String, String>(
|
||||
stateMachineConfigurationConfig, stateMachineTransitions, stateMachineStates);
|
||||
|
||||
StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
|
||||
beanFactory.addBean("taskExecutor", new SyncTaskExecutor());
|
||||
beanFactory.addBean("taskScheduler", new ConcurrentTaskScheduler());
|
||||
stateMachineFactory.setBeanFactory(beanFactory);
|
||||
|
||||
TestListener listener = new TestListener();
|
||||
StateMachine<String,String> stateMachine = stateMachineFactory.getStateMachine();
|
||||
stateMachine.addStateListener(listener);
|
||||
stateMachine.start();
|
||||
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
assertThat(stateMachine, notNullValue());
|
||||
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualBuildTaskViaBeanFactory() throws Exception {
|
||||
Builder<String, String> builder = StateMachineBuilder.builder();
|
||||
|
||||
StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
|
||||
beanFactory.addBean("taskExecutor", new SyncTaskExecutor());
|
||||
beanFactory.addBean("taskScheduler", new ConcurrentTaskScheduler());
|
||||
|
||||
builder.configureConfiguration()
|
||||
.withConfiguration()
|
||||
.beanFactory(beanFactory);
|
||||
|
||||
builder.configureStates()
|
||||
.withStates()
|
||||
.initial("S1").state("S2");
|
||||
|
||||
builder.configureTransitions()
|
||||
.withExternal()
|
||||
.source("S1").target("S2").event("E1")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S2").target("S1").event("E2");
|
||||
|
||||
StateMachine<String, String> stateMachine = builder.build();
|
||||
assertThat(stateMachine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
stateMachine.addStateListener(listener);
|
||||
stateMachine.start();
|
||||
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
assertThat(stateMachine, notNullValue());
|
||||
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualBuildExplicitTaskExecutorAndScheduler() throws Exception {
|
||||
Builder<String, String> builder = StateMachineBuilder.builder();
|
||||
|
||||
builder.configureConfiguration()
|
||||
.withConfiguration()
|
||||
.taskExecutor(new SyncTaskExecutor())
|
||||
.taskScheduler(new ConcurrentTaskScheduler());
|
||||
|
||||
builder.configureStates()
|
||||
.withStates()
|
||||
.initial("S1").state("S2");
|
||||
|
||||
builder.configureTransitions()
|
||||
.withExternal()
|
||||
.source("S1").target("S2").event("E1")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S2").target("S1").event("E2");
|
||||
|
||||
StateMachine<String, String> stateMachine = builder.build();
|
||||
assertThat(stateMachine, notNullValue());
|
||||
TestListener listener = new TestListener();
|
||||
stateMachine.addStateListener(listener);
|
||||
stateMachine.start();
|
||||
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
assertThat(stateMachine, notNullValue());
|
||||
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1"));
|
||||
}
|
||||
|
||||
static class Config extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial("S1").state("S2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source("S1").target("S2").event("E1")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S2").target("S1").event("E2");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestListener extends StateMachineListenerAdapter<String, String> {
|
||||
|
||||
volatile CountDownLatch stateChangedLatch = new CountDownLatch(1);
|
||||
volatile CountDownLatch transitionLatch = new CountDownLatch(0);
|
||||
volatile int stateChangedCount = 0;
|
||||
|
||||
@Override
|
||||
public void stateChanged(State<String, String> from, State<String, String> to) {
|
||||
stateChangedCount++;
|
||||
stateChangedLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transition(Transition<String, String> transition) {
|
||||
transitionLatch.countDown();
|
||||
}
|
||||
|
||||
public void reset(int c1) {
|
||||
reset(c1, 0);
|
||||
}
|
||||
|
||||
public void reset(int c1, int c2) {
|
||||
stateChangedLatch = new CountDownLatch(c1);
|
||||
transitionLatch = new CountDownLatch(c2);
|
||||
stateChangedCount = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user