Add support for default history state
- Add mechanism for transition into a default state vertex in cases where i.e. substate has never been entered, thus meaning there is no history. Without default vertex, submachine now does default entry logic to that region. - Fixes #204
This commit is contained in:
@@ -40,6 +40,7 @@ import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.model.ChoiceData;
|
||||
import org.springframework.statemachine.config.model.EntryData;
|
||||
import org.springframework.statemachine.config.model.ExitData;
|
||||
import org.springframework.statemachine.config.model.HistoryData;
|
||||
import org.springframework.statemachine.config.model.JunctionData;
|
||||
import org.springframework.statemachine.config.model.StateData;
|
||||
import org.springframework.statemachine.config.model.StateMachineModel;
|
||||
@@ -412,6 +413,7 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
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,
|
||||
@@ -458,11 +460,9 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
} else if (stateData.isEnd()) {
|
||||
pseudoState = new DefaultPseudoState<S, E>(PseudoStateKind.END);
|
||||
} else if (stateData.getPseudoStateKind() == PseudoStateKind.HISTORY_SHALLOW) {
|
||||
pseudoState = new HistoryPseudoState<S, E>(PseudoStateKind.HISTORY_SHALLOW);
|
||||
historyState = pseudoState;
|
||||
continue;
|
||||
} else if (stateData.getPseudoStateKind() == PseudoStateKind.HISTORY_DEEP) {
|
||||
pseudoState = new HistoryPseudoState<S, E>(PseudoStateKind.HISTORY_DEEP);
|
||||
historyState = pseudoState;
|
||||
continue;
|
||||
} else if (stateData.getPseudoStateKind() == PseudoStateKind.JOIN) {
|
||||
continue;
|
||||
} else if (stateData.getPseudoStateKind() == PseudoStateKind.FORK) {
|
||||
@@ -489,6 +489,48 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
}
|
||||
|
||||
for (StateData<S, E> stateData : stateDatas) {
|
||||
if (stateData.getPseudoStateKind() == PseudoStateKind.HISTORY_SHALLOW) {
|
||||
State<S, E> defaultState = null;
|
||||
S s = stateData.getState();
|
||||
Collection<HistoryData<S,E>> historys = stateMachineTransitions.getHistorys();
|
||||
for (HistoryData<S,E> history : historys) {
|
||||
if (history.getSource().equals(s)) {
|
||||
defaultState = stateMap.get(history.getTarget());
|
||||
}
|
||||
}
|
||||
StateHolder<S, E> defaultStateHolder = new StateHolder<S, E>(defaultState);
|
||||
StateHolder<S, E> containingStateHolder = new StateHolder<S, E>(stateMap.get(stateData.getParent()));
|
||||
if (containingStateHolder.getState() == null) {
|
||||
holderMap.put((S)stateData.getParent(), containingStateHolder);
|
||||
}
|
||||
PseudoState<S, E> pseudoState = new HistoryPseudoState<S, E>(PseudoStateKind.HISTORY_SHALLOW, defaultStateHolder, containingStateHolder);
|
||||
state = buildStateInternal(stateData.getState(), stateData.getDeferred(), stateData.getEntryActions(),
|
||||
stateData.getExitActions(), pseudoState);
|
||||
states.add(state);
|
||||
stateMap.put(stateData.getState(), state);
|
||||
historyState = pseudoState;
|
||||
} else if (stateData.getPseudoStateKind() == PseudoStateKind.HISTORY_DEEP) {
|
||||
State<S, E> defaultState = null;
|
||||
S s = stateData.getState();
|
||||
Collection<HistoryData<S,E>> historys = stateMachineTransitions.getHistorys();
|
||||
for (HistoryData<S,E> history : historys) {
|
||||
if (history.getSource().equals(s)) {
|
||||
defaultState = stateMap.get(history.getTarget());
|
||||
}
|
||||
}
|
||||
StateHolder<S, E> defaultStateHolder = new StateHolder<S, E>(defaultState);
|
||||
StateHolder<S, E> containingStateHolder = new StateHolder<S, E>(stateMap.get(stateData.getParent()));
|
||||
if (containingStateHolder.getState() == null) {
|
||||
holderMap.put((S)stateData.getParent(), containingStateHolder);
|
||||
}
|
||||
PseudoState<S, E> pseudoState = new HistoryPseudoState<S, E>(PseudoStateKind.HISTORY_DEEP, defaultStateHolder, containingStateHolder);
|
||||
state = buildStateInternal(stateData.getState(), stateData.getDeferred(), stateData.getEntryActions(),
|
||||
stateData.getExitActions(), pseudoState);
|
||||
states.add(state);
|
||||
stateMap.put(stateData.getState(), state);
|
||||
historyState = pseudoState;
|
||||
}
|
||||
|
||||
if (stateData.getPseudoStateKind() == PseudoStateKind.CHOICE) {
|
||||
S s = stateData.getState();
|
||||
List<ChoiceData<S, E>> list = stateMachineTransitions.getChoices().get(s);
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.statemachine.config.configurers.DefaultEntryTransitio
|
||||
import org.springframework.statemachine.config.configurers.DefaultExitTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.DefaultExternalTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.DefaultForkTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.DefaultHistoryTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.DefaultInternalTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.DefaultJoinTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.DefaultJunctionTransitionConfigurer;
|
||||
@@ -39,6 +40,7 @@ import org.springframework.statemachine.config.configurers.EntryTransitionConfig
|
||||
import org.springframework.statemachine.config.configurers.ExitTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.ExternalTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.ForkTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.HistoryTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.InternalTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.JoinTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.JunctionTransitionConfigurer;
|
||||
@@ -47,6 +49,7 @@ import org.springframework.statemachine.config.model.ChoiceData;
|
||||
import org.springframework.statemachine.config.model.ConfigurationData;
|
||||
import org.springframework.statemachine.config.model.EntryData;
|
||||
import org.springframework.statemachine.config.model.ExitData;
|
||||
import org.springframework.statemachine.config.model.HistoryData;
|
||||
import org.springframework.statemachine.config.model.JunctionData;
|
||||
import org.springframework.statemachine.config.model.TransitionData;
|
||||
import org.springframework.statemachine.config.model.TransitionsData;
|
||||
@@ -74,6 +77,7 @@ public class StateMachineTransitionBuilder<S, E>
|
||||
private final Map<S, List<S>> joins = new HashMap<S, List<S>>();
|
||||
private final Collection<EntryData<S, E>> entryData = new ArrayList<EntryData<S, E>>();
|
||||
private final Collection<ExitData<S, E>> exitData = new ArrayList<ExitData<S, E>>();
|
||||
private final Collection<HistoryData<S, E>> historyData = new ArrayList<HistoryData<S, E>>();
|
||||
|
||||
/**
|
||||
* Instantiates a new state machine transition builder.
|
||||
@@ -104,7 +108,7 @@ public class StateMachineTransitionBuilder<S, E>
|
||||
|
||||
@Override
|
||||
protected TransitionsData<S, E> performBuild() throws Exception {
|
||||
return new TransitionsData<S, E>(transitionData, choices, junctions, forks, joins, entryData, exitData);
|
||||
return new TransitionsData<S, E>(transitionData, choices, junctions, forks, joins, entryData, exitData, historyData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,6 +156,11 @@ public class StateMachineTransitionBuilder<S, E>
|
||||
return apply(new DefaultExitTransitionConfigurer<S, E>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoryTransitionConfigurer<S, E> withHistory() throws Exception {
|
||||
return apply(new DefaultHistoryTransitionConfigurer<S, E>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the transition.
|
||||
*
|
||||
@@ -236,4 +245,14 @@ public class StateMachineTransitionBuilder<S, E>
|
||||
public void addJoin(S target, List<S> sources) {
|
||||
this.joins.put(target, sources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the default history.
|
||||
*
|
||||
* @param source the source
|
||||
* @param target the target
|
||||
*/
|
||||
public void addDefaultHistory(S source, S target) {
|
||||
this.historyData.add(new HistoryData<S, E>(source, target));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.springframework.statemachine.config.configurers.EntryTransitionConfig
|
||||
import org.springframework.statemachine.config.configurers.ExitTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.ExternalTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.ForkTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.HistoryTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.InternalTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.JoinTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.JunctionTransitionConfigurer;
|
||||
@@ -114,4 +115,12 @@ public interface StateMachineTransitionConfigurer<S, E> {
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
ExitTransitionConfigurer<S, E> withExit() throws Exception;
|
||||
|
||||
/**
|
||||
* Gets a configurer for default history transition.
|
||||
*
|
||||
* @return {@link HistoryTransitionConfigurer} for chaining
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
HistoryTransitionConfigurer<S, E> withHistory() throws Exception;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2016 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.statemachine.config.builders.StateMachineTransitionBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.model.TransitionsData;
|
||||
|
||||
/**
|
||||
* Default implementation of a {@link HistoryTransitionConfigurer}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public class DefaultHistoryTransitionConfigurer<S, E>
|
||||
extends AnnotationConfigurerAdapter<TransitionsData<S, E>, StateMachineTransitionConfigurer<S, E>, StateMachineTransitionBuilder<S, E>>
|
||||
implements HistoryTransitionConfigurer<S, E> {
|
||||
|
||||
private S source;
|
||||
private S target;
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionBuilder<S, E> builder) throws Exception {
|
||||
builder.addDefaultHistory(source, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoryTransitionConfigurer<S, E> source(S source) {
|
||||
this.source = source;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoryTransitionConfigurer<S, E> target(S target) {
|
||||
this.target = target;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2016 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.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurerBuilder;
|
||||
import org.springframework.statemachine.transition.Transition;
|
||||
|
||||
/**
|
||||
* {@code TransitionConfigurer} interface for configuring {@link Transition}
|
||||
* with default history state.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public interface HistoryTransitionConfigurer<S, E>
|
||||
extends AnnotationConfigurerBuilder<StateMachineTransitionConfigurer<S, E>> {
|
||||
|
||||
/**
|
||||
* Specify a source state {@code S} for this {@link Transition}.
|
||||
*
|
||||
* @param source the source state {@code S}
|
||||
* @return configurer for chaining
|
||||
*/
|
||||
HistoryTransitionConfigurer<S, E> source(S source);
|
||||
|
||||
/**
|
||||
* Specify a target state {@code S} for this {@link Transition}.
|
||||
*
|
||||
* @param target the target state {@code S}
|
||||
* @return configurer for chaining
|
||||
*/
|
||||
HistoryTransitionConfigurer<S, E> target(S target);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2016 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.model;
|
||||
|
||||
/**
|
||||
* A simple data object keeping history related configs in a same place.
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public class HistoryData<S, E> {
|
||||
private final S source;
|
||||
private final S target;
|
||||
|
||||
/**
|
||||
* Instantiates a new history data.
|
||||
*
|
||||
* @param source the source
|
||||
* @param target the target
|
||||
*/
|
||||
public HistoryData(S source, S target) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source.
|
||||
*
|
||||
* @return the source
|
||||
*/
|
||||
public S getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the target.
|
||||
*
|
||||
* @return the target
|
||||
*/
|
||||
public S getTarget() {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ public class TransitionsData<S, E> {
|
||||
private final Map<S, List<S>> joins;
|
||||
private final Collection<EntryData<S, E>> entrys;
|
||||
private final Collection<ExitData<S, E>> exits;
|
||||
private final Collection<HistoryData<S, E>> historys;
|
||||
|
||||
/**
|
||||
* Instantiates a new transitions data.
|
||||
@@ -43,7 +44,7 @@ public class TransitionsData<S, E> {
|
||||
* @param transitionsData the transitions data
|
||||
*/
|
||||
public TransitionsData(Collection<TransitionData<S, E>> transitionsData) {
|
||||
this(transitionsData, null, null, null, null, null, null);
|
||||
this(transitionsData, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,10 +57,11 @@ public class TransitionsData<S, E> {
|
||||
* @param joins the joins
|
||||
* @param entrys the entrys
|
||||
* @param exits the exits
|
||||
* @param historys the historys
|
||||
*/
|
||||
public TransitionsData(Collection<TransitionData<S, E>> transitionsData, Map<S, List<ChoiceData<S, E>>> choices,
|
||||
Map<S, List<JunctionData<S, E>>> junctions, Map<S, List<S>> forks, Map<S, List<S>> joins, Collection<EntryData<S, E>> entrys,
|
||||
Collection<ExitData<S, E>> exits) {
|
||||
Collection<ExitData<S, E>> exits, Collection<HistoryData<S, E>> historys) {
|
||||
this.transitions = transitionsData;
|
||||
this.choices = choices;
|
||||
this.junctions = junctions;
|
||||
@@ -67,6 +69,7 @@ public class TransitionsData<S, E> {
|
||||
this.joins = joins;
|
||||
this.entrys = entrys;
|
||||
this.exits = exits;
|
||||
this.historys = historys;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,4 +134,13 @@ public class TransitionsData<S, E> {
|
||||
public Collection<ExitData<S, E>> getExits() {
|
||||
return exits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the historys.
|
||||
*
|
||||
* @return the historys
|
||||
*/
|
||||
public Collection<HistoryData<S, E>> getHistorys() {
|
||||
return historys;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,24 +28,57 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class HistoryPseudoState<S, E> extends AbstractPseudoState<S, E> {
|
||||
|
||||
private final StateHolder<S, E> defaultState;
|
||||
private final StateHolder<S, E> containingState;
|
||||
private State<S, E> state;
|
||||
|
||||
/**
|
||||
* Instantiates a new history pseudo state.
|
||||
*
|
||||
* @param kind the kind
|
||||
* @param containingState the parent containing state
|
||||
*/
|
||||
public HistoryPseudoState(PseudoStateKind kind) {
|
||||
public HistoryPseudoState(PseudoStateKind kind, StateHolder<S, E> containingState) {
|
||||
this(kind, containingState, new StateHolder<S, E>(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new history pseudo state.
|
||||
*
|
||||
* @param kind the kind
|
||||
* @param defaultState the default history state
|
||||
* @param containingState the parent containing state
|
||||
*/
|
||||
public HistoryPseudoState(PseudoStateKind kind, StateHolder<S, E> defaultState, StateHolder<S, E> containingState) {
|
||||
super(kind);
|
||||
Assert.isTrue(PseudoStateKind.HISTORY_SHALLOW == kind || PseudoStateKind.HISTORY_DEEP == kind,
|
||||
"Pseudo state must be either shallow or deep");
|
||||
Assert.notNull(defaultState, "Holder defaultState must be set");
|
||||
Assert.notNull(containingState, "Holder containingState must be set");
|
||||
this.defaultState = defaultState;
|
||||
this.containingState = containingState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State<S, E> entry(StateContext<S, E> context) {
|
||||
return state;
|
||||
// if no logged history or history is final state,
|
||||
// go to default state. go to containing parent if
|
||||
// we have no history and there's no default state.
|
||||
if (state == null) {
|
||||
if (defaultState.getState() == null) {
|
||||
return containingState.getState();
|
||||
} else {
|
||||
return defaultState.getState();
|
||||
}
|
||||
} else {
|
||||
if (defaultState.getState() != null && state.getPseudoState() != null && state.getPseudoState().getKind() == PseudoStateKind.END) {
|
||||
return defaultState.getState();
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the current recorded state.
|
||||
*
|
||||
@@ -63,5 +96,4 @@ public class HistoryPseudoState<S, E> extends AbstractPseudoState<S, E> {
|
||||
public State<S, E> getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -73,23 +73,23 @@ public abstract class AbstractStateMachineTests {
|
||||
}
|
||||
|
||||
public enum TestEvents {
|
||||
E1,E2,E3,E4,EF
|
||||
E1,E2,E3,E4,EF,EH
|
||||
}
|
||||
|
||||
public static enum TestStates2 {
|
||||
BUSY, PLAYING, PAUSED,
|
||||
IDLE, CLOSED, OPEN,
|
||||
PAUSED1, PAUSED2
|
||||
BUSY, PLAYING, PAUSED,
|
||||
IDLE, CLOSED, OPEN,
|
||||
PAUSED1, PAUSED2
|
||||
}
|
||||
|
||||
public static enum TestStates3 {
|
||||
READY,
|
||||
FORK, JOIN,
|
||||
TASKS, T1, T1E, T2, T2E, T3, T3E
|
||||
READY,
|
||||
FORK, JOIN,
|
||||
TASKS, T1, T1E, T2, T2E, T3, T3E
|
||||
}
|
||||
|
||||
public static enum TestEvents2 {
|
||||
PLAY, STOP, PAUSE, EJECT, LOAD
|
||||
PLAY, STOP, PAUSE, EJECT, LOAD
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -77,7 +77,7 @@ public class StateMachineModelTests {
|
||||
Map<String, List<JunctionData<String, String>>> junctions = new HashMap<>();
|
||||
Map<String, List<String>> forks = new HashMap<>();
|
||||
Map<String, List<String>> joins = new HashMap<>();
|
||||
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitions, choices, junctions, forks, joins, null, null);
|
||||
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitions, choices, junctions, forks, joins, null, null, null);
|
||||
|
||||
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<>(configurationData, statesData, transitionsData);
|
||||
ObjectStateMachineFactory<String, String> factory = new ObjectStateMachineFactory<>(stateMachineModel);
|
||||
|
||||
@@ -55,6 +55,20 @@ public class HistoryStateTests extends AbstractStateMachineTests {
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S2, TestStates.S21));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testShallowNoHistoryDefaultsNormalEntry() {
|
||||
context.register(BaseConfig.class, Config1.class);
|
||||
context.refresh();
|
||||
ObjectStateMachine<TestStates,TestEvents> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
machine.start();
|
||||
machine.sendEvent(TestEvents.E4);
|
||||
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S2, TestStates.S20));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testDeep() {
|
||||
@@ -88,6 +102,40 @@ public class HistoryStateTests extends AbstractStateMachineTests {
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S2, TestStates.S21, TestStates.S211));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testDefaultNotEntered() {
|
||||
context.register(BaseConfig.class, Config4.class);
|
||||
context.refresh();
|
||||
ObjectStateMachine<TestStates,TestEvents> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
machine.start();
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S1));
|
||||
machine.sendEvent(TestEvents.EH);
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S3, TestStates.S33));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testDefaultHistoryIsFinal() {
|
||||
context.register(BaseConfig.class, Config4.class);
|
||||
context.refresh();
|
||||
ObjectStateMachine<TestStates,TestEvents> machine =
|
||||
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
|
||||
assertThat(machine, notNullValue());
|
||||
machine.start();
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S1));
|
||||
machine.sendEvent(TestEvents.E1);
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S3, TestStates.S30));
|
||||
machine.sendEvent(TestEvents.EF);
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S3, TestStates.SF));
|
||||
machine.sendEvent(TestEvents.E4);
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S1));
|
||||
machine.sendEvent(TestEvents.EH);
|
||||
assertThat(machine.getState().getIds(), contains(TestStates.S3, TestStates.S33));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
static class Config1 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
|
||||
@@ -106,7 +154,6 @@ public class HistoryStateTests extends AbstractStateMachineTests {
|
||||
.state(TestStates.S20)
|
||||
.state(TestStates.S21)
|
||||
.history(TestStates.SH, History.SHALLOW);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -239,4 +286,64 @@ public class HistoryStateTests extends AbstractStateMachineTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
static class Config4 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(TestStates.S1)
|
||||
.state(TestStates.S1)
|
||||
.state(TestStates.S3)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(TestStates.S3)
|
||||
.initial(TestStates.S30)
|
||||
.state(TestStates.S31)
|
||||
.state(TestStates.S32)
|
||||
.state(TestStates.S33)
|
||||
.end(TestStates.SF)
|
||||
.history(TestStates.SH, History.SHALLOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<TestStates, TestEvents> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source(TestStates.S1)
|
||||
.target(TestStates.S3)
|
||||
.event(TestEvents.E1)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TestStates.S30)
|
||||
.target(TestStates.S31)
|
||||
.event(TestEvents.E2)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TestStates.S31)
|
||||
.target(TestStates.S32)
|
||||
.event(TestEvents.E3)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TestStates.S30)
|
||||
.target(TestStates.SF)
|
||||
.event(TestEvents.EF)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TestStates.S3)
|
||||
.target(TestStates.S1)
|
||||
.event(TestEvents.E4)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TestStates.S1)
|
||||
.target(TestStates.SH)
|
||||
.event(TestEvents.EH)
|
||||
.and()
|
||||
.withHistory()
|
||||
.source(TestStates.SH)
|
||||
.target(TestStates.S33);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.model.ChoiceData;
|
||||
import org.springframework.statemachine.config.model.EntryData;
|
||||
import org.springframework.statemachine.config.model.ExitData;
|
||||
import org.springframework.statemachine.config.model.HistoryData;
|
||||
import org.springframework.statemachine.config.model.JunctionData;
|
||||
import org.springframework.statemachine.config.model.StateData;
|
||||
import org.springframework.statemachine.config.model.StateMachineComponentResolver;
|
||||
@@ -72,6 +73,7 @@ public class UmlModelParser {
|
||||
private final Collection<TransitionData<String, String>> transitionDatas = new ArrayList<TransitionData<String, String>>();
|
||||
private final Collection<EntryData<String, String>> entrys = new ArrayList<EntryData<String, String>>();
|
||||
private final Collection<ExitData<String, String>> exits = new ArrayList<ExitData<String, String>>();
|
||||
private final Collection<HistoryData<String, String>> historys = new ArrayList<HistoryData<String, String>>();
|
||||
private final Map<String, LinkedList<ChoiceData<String, String>>> choices = new HashMap<String, LinkedList<ChoiceData<String,String>>>();
|
||||
private final Map<String, LinkedList<JunctionData<String, String>>> junctions = new HashMap<String, LinkedList<JunctionData<String,String>>>();
|
||||
private final Map<String, List<String>> forks = new HashMap<String, List<String>>();
|
||||
@@ -112,7 +114,7 @@ public class UmlModelParser {
|
||||
HashMap<String, List<JunctionData<String, String>>> junctionsCopy = new HashMap<String, List<JunctionData<String, String>>>();
|
||||
junctionsCopy.putAll(junctions);
|
||||
return new DataHolder(new StatesData<>(stateDatas),
|
||||
new TransitionsData<String, String>(transitionDatas, choicesCopy, junctionsCopy, forks, joins, entrys, exits));
|
||||
new TransitionsData<String, String>(transitionDatas, choicesCopy, junctionsCopy, forks, joins, entrys, exits, historys));
|
||||
}
|
||||
|
||||
private void handleRegion(Region region) {
|
||||
@@ -259,6 +261,10 @@ public class UmlModelParser {
|
||||
forks.put(transition.getSource().getName(), list);
|
||||
}
|
||||
list.add(transition.getTarget().getName());
|
||||
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.SHALLOW_HISTORY_LITERAL) {
|
||||
historys.add(new HistoryData<String, String>(transition.getSource().getName(), transition.getTarget().getName()));
|
||||
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.DEEP_HISTORY_LITERAL) {
|
||||
historys.add(new HistoryData<String, String>(transition.getSource().getName(), transition.getTarget().getName()));
|
||||
}
|
||||
}
|
||||
if (transition.getTarget() instanceof Pseudostate) {
|
||||
|
||||
@@ -462,6 +462,18 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testSimpleHistoryDefault() {
|
||||
context.register(Config12.class);
|
||||
context.refresh();
|
||||
StateMachine<String, String> stateMachine = context.getBean(StateMachine.class);
|
||||
stateMachine.start();
|
||||
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1"));
|
||||
stateMachine.sendEvent("E4");
|
||||
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S2", "S22"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config2 extends StateMachineConfigurerAdapter<String, String> {
|
||||
@@ -681,6 +693,23 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config12 extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
|
||||
model
|
||||
.withModel()
|
||||
.factory(modelFactory());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StateMachineModelFactory<String, String> modelFactory() {
|
||||
return new UmlStateMachineModelFactory("classpath:org/springframework/statemachine/uml/simple-history-default.uml");
|
||||
}
|
||||
}
|
||||
|
||||
public static class LatchAction implements Action<String, String> {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"/>
|
||||
@@ -0,0 +1,243 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/viewpoints/policy/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_T1ONMAPSEeaXyaQL1WyV3A" type="PapyrusUMLStateMachineDiagram" name="StateMachine Diagram" measurementUnit="Pixel">
|
||||
<children xmi:type="notation:Shape" xmi:id="_T1ONMQPSEeaXyaQL1WyV3A" type="2000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_T1ONMgPSEeaXyaQL1WyV3A" type="2001">
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_T1ONMwPSEeaXyaQL1WyV3A" width="700" height="23"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_T1ONNAPSEeaXyaQL1WyV3A" type="2002">
|
||||
<children xmi:type="notation:Shape" xmi:id="_T1ONNQPSEeaXyaQL1WyV3A" type="3000">
|
||||
<eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_T1ONNgPSEeaXyaQL1WyV3A" source="RegionAnnotationKey">
|
||||
<details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_T1ONNwPSEeaXyaQL1WyV3A" key="RegionZoneKey" value=""/>
|
||||
</eAnnotations>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_T1ONOAPSEeaXyaQL1WyV3A" type="3002">
|
||||
<children xmi:type="notation:Shape" xmi:id="_e88IgAPSEeaXyaQL1WyV3A" type="6000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_e88IggPSEeaXyaQL1WyV3A" type="6001">
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_hF7Y0APTEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_e88IgwPSEeaXyaQL1WyV3A" type="19003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_e88IhAPSEeaXyaQL1WyV3A" x="40"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_e88IhQPSEeaXyaQL1WyV3A" type="6002">
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_e88IhgPSEeaXyaQL1WyV3A" y="-1"/>
|
||||
</children>
|
||||
<element xmi:type="uml:State" href="simple-history-default.uml#_e85FMAPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_e88IgQPSEeaXyaQL1WyV3A" x="110" y="87" height="161"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_hkW2sAPSEeaXyaQL1WyV3A" type="6000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_hkW2sgPSEeaXyaQL1WyV3A" type="6001">
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_j1AqsAPSEeaXyaQL1WyV3A" width="341" height="23"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_hkXdwAPSEeaXyaQL1WyV3A" type="19003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_hkXdwQPSEeaXyaQL1WyV3A" x="40"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_hkXdwgPSEeaXyaQL1WyV3A" type="6002">
|
||||
<eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_kZ9K0APSEeaXyaQL1WyV3A" source="PapyrusCSSForceValue">
|
||||
<details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_kZ9K0QPSEeaXyaQL1WyV3A" key="visible" value="true"/>
|
||||
</eAnnotations>
|
||||
<children xmi:type="notation:Shape" xmi:id="_kZ9x4APSEeaXyaQL1WyV3A" type="3000">
|
||||
<eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_kZ9x5APSEeaXyaQL1WyV3A" source="RegionAnnotationKey">
|
||||
<details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_kZ9x5QPSEeaXyaQL1WyV3A" key="RegionZoneKey" value=""/>
|
||||
</eAnnotations>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_kZ9x4gPSEeaXyaQL1WyV3A" type="3002">
|
||||
<children xmi:type="notation:Shape" xmi:id="_kZ_AAAPSEeaXyaQL1WyV3A" type="6000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_kZ_AAgPSEeaXyaQL1WyV3A" type="6001"/>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_kZ_AAwPSEeaXyaQL1WyV3A" type="19003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_kZ_ABAPSEeaXyaQL1WyV3A" x="40"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_kZ_ABQPSEeaXyaQL1WyV3A" type="6002">
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_kZ_ABgPSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<element xmi:type="uml:State" href="simple-history-default.uml#_kZ-Y8APSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_kZ_AAQPSEeaXyaQL1WyV3A" x="100" y="37"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_kxSswAPSEeaXyaQL1WyV3A" type="6000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_kxSswgPSEeaXyaQL1WyV3A" type="6001"/>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_kxSswwPSEeaXyaQL1WyV3A" type="19003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_kxSsxAPSEeaXyaQL1WyV3A" x="40"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_kxSsxQPSEeaXyaQL1WyV3A" type="6002">
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_kxSsxgPSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<element xmi:type="uml:State" href="simple-history-default.uml#_kxNNMAPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_kxSswQPSEeaXyaQL1WyV3A" x="240" y="37"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_yTtv8APSEeaXyaQL1WyV3A" type="8000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_yTtv8gPSEeaXyaQL1WyV3A" type="8001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_yTtv8wPSEeaXyaQL1WyV3A" x="25" y="3"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_yTtv9APSEeaXyaQL1WyV3A" type="8002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_yTtv9QPSEeaXyaQL1WyV3A" x="25" y="-10"/>
|
||||
</children>
|
||||
<element xmi:type="uml:Pseudostate" href="simple-history-default.uml#_yTlNEAPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_yTtv8QPSEeaXyaQL1WyV3A" x="20" y="37"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_9MwWEAPSEeaXyaQL1WyV3A" type="13000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_9Mw9IAPSEeaXyaQL1WyV3A" type="13001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_9Mw9IQPSEeaXyaQL1WyV3A" x="20" y="-20"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_9Mw9IgPSEeaXyaQL1WyV3A" type="13002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_9Mw9IwPSEeaXyaQL1WyV3A" x="25" y="-10"/>
|
||||
</children>
|
||||
<element xmi:type="uml:Pseudostate" href="simple-history-default.uml#_9MnMIAPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9MwWEQPSEeaXyaQL1WyV3A" x="100" y="117"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_RrF3AAf7EeayEI1yTJhWhg" type="6000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_RrF3Agf7EeayEI1yTJhWhg" type="6001"/>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_RrGeEAf7EeayEI1yTJhWhg" type="19003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_RrGeEQf7EeayEI1yTJhWhg" x="40"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_RrGeEgf7EeayEI1yTJhWhg" type="6002">
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_RrGeEwf7EeayEI1yTJhWhg"/>
|
||||
</children>
|
||||
<element xmi:type="uml:State" href="simple-history-default.uml#_Rq5CsAf7EeayEI1yTJhWhg"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_RrF3AQf7EeayEI1yTJhWhg" x="240" y="117"/>
|
||||
</children>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_kZ9x4wPSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<element xmi:type="uml:Region" href="simple-history-default.uml#_kZ9K0gPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_kZ9x4QPSEeaXyaQL1WyV3A" width="341" height="178"/>
|
||||
</children>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_hkXdwwPSEeaXyaQL1WyV3A" y="23" width="341" height="178"/>
|
||||
</children>
|
||||
<element xmi:type="uml:State" href="simple-history-default.uml#_hkTzYAPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_hkW2sQPSEeaXyaQL1WyV3A" x="230" y="47" width="341" height="201"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_phuV4APSEeaXyaQL1WyV3A" type="8000">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_phuV4gPSEeaXyaQL1WyV3A" type="8001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_phuV4wPSEeaXyaQL1WyV3A" x="25" y="3"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_phuV5APSEeaXyaQL1WyV3A" type="8002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_phuV5QPSEeaXyaQL1WyV3A" x="25" y="-10"/>
|
||||
</children>
|
||||
<element xmi:type="uml:Pseudostate" href="simple-history-default.uml#_phoPQAPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_phuV4QPSEeaXyaQL1WyV3A" x="30" y="87"/>
|
||||
</children>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_T1ONOQPSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<element xmi:type="uml:Region" href="simple-history-default.uml#_T1NmIAPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_T1ONOgPSEeaXyaQL1WyV3A" width="700" height="287"/>
|
||||
</children>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_T1ONOwPSEeaXyaQL1WyV3A" y="23" width="700" height="287"/>
|
||||
</children>
|
||||
<element xmi:type="uml:StateMachine" href="simple-history-default.uml#_T1M_EAPSEeaXyaQL1WyV3A"/>
|
||||
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_T1ONPAPSEeaXyaQL1WyV3A" x="30" y="30" width="700" height="310"/>
|
||||
</children>
|
||||
<styles xmi:type="notation:StringValueStyle" xmi:id="_T1ONPQPSEeaXyaQL1WyV3A" name="diagram_compatibility_version" stringValue="1.1.0"/>
|
||||
<styles xmi:type="notation:DiagramStyle" xmi:id="_T1ONPgPSEeaXyaQL1WyV3A"/>
|
||||
<styles xmi:type="style:PapyrusViewStyle" xmi:id="_T1ONPwPSEeaXyaQL1WyV3A">
|
||||
<owner xmi:type="uml:Model" href="simple-history-default.uml#_T1LJ4APSEeaXyaQL1WyV3A"/>
|
||||
</styles>
|
||||
<element xmi:type="uml:StateMachine" href="simple-history-default.uml#_T1M_EAPSEeaXyaQL1WyV3A"/>
|
||||
<edges xmi:type="notation:Connector" xmi:id="_tS0o8APSEeaXyaQL1WyV3A" type="7000" source="_phuV4APSEeaXyaQL1WyV3A" target="_e88IgAPSEeaXyaQL1WyV3A">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_tS0o8wPSEeaXyaQL1WyV3A" type="7001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_tS0o9APSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_tS0o9QPSEeaXyaQL1WyV3A" type="7002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_tS0o9gPSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_tS0o9wPSEeaXyaQL1WyV3A" type="7003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_tS1QAAPSEeaXyaQL1WyV3A" y="60"/>
|
||||
</children>
|
||||
<styles xmi:type="notation:FontStyle" xmi:id="_tS0o8QPSEeaXyaQL1WyV3A"/>
|
||||
<element xmi:type="uml:Transition" href="simple-history-default.uml#_tSsGEAPSEeaXyaQL1WyV3A"/>
|
||||
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_tS0o8gPSEeaXyaQL1WyV3A" points="[7, -6, -81, 0]$[87, -10, -1, -4]"/>
|
||||
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_tTIyAAPSEeaXyaQL1WyV3A" id="(1.0,0.45)"/>
|
||||
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_tTIyAQPSEeaXyaQL1WyV3A" id="(0.0,0.10638297872340426)"/>
|
||||
</edges>
|
||||
<edges xmi:type="notation:Connector" xmi:id="_vV8-UAPSEeaXyaQL1WyV3A" type="7000" source="_e88IgAPSEeaXyaQL1WyV3A" target="_hkW2sAPSEeaXyaQL1WyV3A">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_vV8-UwPSEeaXyaQL1WyV3A" type="7001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_vV8-VAPSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_vV8-VQPSEeaXyaQL1WyV3A" type="7002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_vV8-VgPSEeaXyaQL1WyV3A" x="-10" y="-13"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_vV8-VwPSEeaXyaQL1WyV3A" type="7003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_vV8-WAPSEeaXyaQL1WyV3A" y="60"/>
|
||||
</children>
|
||||
<styles xmi:type="notation:FontStyle" xmi:id="_vV8-UQPSEeaXyaQL1WyV3A"/>
|
||||
<element xmi:type="uml:Transition" href="simple-history-default.uml#_vV1CgAPSEeaXyaQL1WyV3A"/>
|
||||
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_vV8-UgPSEeaXyaQL1WyV3A" points="[38, 4, -100, -11]$[120, 11, -18, -4]"/>
|
||||
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_vWTjoAPSEeaXyaQL1WyV3A" id="(1.0,0.14184397163120568)"/>
|
||||
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_vWTjoQPSEeaXyaQL1WyV3A" id="(0.0,0.29850746268656714)"/>
|
||||
</edges>
|
||||
<edges xmi:type="notation:Connector" xmi:id="_xIpD8APSEeaXyaQL1WyV3A" type="7000" source="_kZ_AAAPSEeaXyaQL1WyV3A" target="_kxSswAPSEeaXyaQL1WyV3A">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_xIpD8wPSEeaXyaQL1WyV3A" type="7001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_xIpD9APSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_xIpD9QPSEeaXyaQL1WyV3A" type="7002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_xIpD9gPSEeaXyaQL1WyV3A" x="-1" y="-11"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_xIpD9wPSEeaXyaQL1WyV3A" type="7003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_xIpD-APSEeaXyaQL1WyV3A" y="60"/>
|
||||
</children>
|
||||
<styles xmi:type="notation:FontStyle" xmi:id="_xIpD8QPSEeaXyaQL1WyV3A"/>
|
||||
<element xmi:type="uml:Transition" href="simple-history-default.uml#_xIeE0APSEeaXyaQL1WyV3A"/>
|
||||
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_xIpD8gPSEeaXyaQL1WyV3A" points="[38, 5, -62, 5]$[102, 3, 2, 3]"/>
|
||||
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_xJCFgAPSEeaXyaQL1WyV3A" id="(1.0,0.44680851063829785)"/>
|
||||
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_xJCFgQPSEeaXyaQL1WyV3A" id="(0.0,0.425531914893617)"/>
|
||||
</edges>
|
||||
<edges xmi:type="notation:Connector" xmi:id="_2lE3cAPSEeaXyaQL1WyV3A" type="7000" source="_yTtv8APSEeaXyaQL1WyV3A" target="_kZ_AAAPSEeaXyaQL1WyV3A">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_2lE3cwPSEeaXyaQL1WyV3A" type="7001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_2lE3dAPSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_2lE3dQPSEeaXyaQL1WyV3A" type="7002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_2lE3dgPSEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_2lE3dwPSEeaXyaQL1WyV3A" type="7003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_2lE3eAPSEeaXyaQL1WyV3A" y="60"/>
|
||||
</children>
|
||||
<styles xmi:type="notation:FontStyle" xmi:id="_2lE3cQPSEeaXyaQL1WyV3A"/>
|
||||
<element xmi:type="uml:Transition" href="simple-history-default.uml#_2k8UkAPSEeaXyaQL1WyV3A"/>
|
||||
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_2lE3cgPSEeaXyaQL1WyV3A" points="[8, 1, -75, 0]$[77, -10, -6, -11]"/>
|
||||
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_2lcD0APSEeaXyaQL1WyV3A" id="(1.0,0.45)"/>
|
||||
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_2lcD0QPSEeaXyaQL1WyV3A" id="(0.0,0.2127659574468085)"/>
|
||||
</edges>
|
||||
<edges xmi:type="notation:Connector" xmi:id="_DE-GoAPTEeaXyaQL1WyV3A" type="7000" source="_e88IgAPSEeaXyaQL1WyV3A" target="_9MwWEAPSEeaXyaQL1WyV3A">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_DE-tsAPTEeaXyaQL1WyV3A" type="7001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_DE-tsQPTEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_DE-tsgPTEeaXyaQL1WyV3A" type="7002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_DE-tswPTEeaXyaQL1WyV3A" x="-48" y="-21"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_DE-ttAPTEeaXyaQL1WyV3A" type="7003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_DE-ttQPTEeaXyaQL1WyV3A" y="60"/>
|
||||
</children>
|
||||
<styles xmi:type="notation:FontStyle" xmi:id="_DE-GoQPTEeaXyaQL1WyV3A"/>
|
||||
<element xmi:type="uml:Transition" href="simple-history-default.uml#_DEzHgAPTEeaXyaQL1WyV3A"/>
|
||||
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_DE-GogPTEeaXyaQL1WyV3A" points="[40, 18, -150, -72]$[193, 98, 3, 8]"/>
|
||||
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_DFec8APTEeaXyaQL1WyV3A" id="(1.0,0.37267080745341613)"/>
|
||||
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_DFec8QPTEeaXyaQL1WyV3A" id="(0.0,0.3)"/>
|
||||
</edges>
|
||||
<edges xmi:type="notation:Connector" xmi:id="_JsAsEAPTEeaXyaQL1WyV3A" type="7000" source="_hkW2sAPSEeaXyaQL1WyV3A" target="_e88IgAPSEeaXyaQL1WyV3A">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_JsAsEwPTEeaXyaQL1WyV3A" type="7001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_JsAsFAPTEeaXyaQL1WyV3A"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_JsAsFQPTEeaXyaQL1WyV3A" type="7002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_JsAsFgPTEeaXyaQL1WyV3A" x="-12" y="14"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_JsAsFwPTEeaXyaQL1WyV3A" type="7003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_JsAsGAPTEeaXyaQL1WyV3A" y="60"/>
|
||||
</children>
|
||||
<styles xmi:type="notation:FontStyle" xmi:id="_JsAsEQPTEeaXyaQL1WyV3A"/>
|
||||
<element xmi:type="uml:Transition" href="simple-history-default.uml#_Jr4JMAPTEeaXyaQL1WyV3A"/>
|
||||
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_JsAsEgPTEeaXyaQL1WyV3A" points="[-16, -10, 111, 65]$[-136, -68, -9, 7]"/>
|
||||
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_JscJ4APTEeaXyaQL1WyV3A" id="(0.0,0.7960199004975125)"/>
|
||||
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_JscJ4QPTEeaXyaQL1WyV3A" id="(1.0,0.8226950354609929)"/>
|
||||
</edges>
|
||||
<edges xmi:type="notation:Connector" xmi:id="_VhKJoAf7EeayEI1yTJhWhg" type="7000" source="_9MwWEAPSEeaXyaQL1WyV3A" target="_RrF3AAf7EeayEI1yTJhWhg">
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_VhKwsAf7EeayEI1yTJhWhg" type="7001">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_VhKwsQf7EeayEI1yTJhWhg"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_VhKwsgf7EeayEI1yTJhWhg" type="7002">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_VhKwswf7EeayEI1yTJhWhg"/>
|
||||
</children>
|
||||
<children xmi:type="notation:DecorationNode" xmi:id="_VhKwtAf7EeayEI1yTJhWhg" type="7003">
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_VhKwtQf7EeayEI1yTJhWhg" y="60"/>
|
||||
</children>
|
||||
<styles xmi:type="notation:FontStyle" xmi:id="_VhKJoQf7EeayEI1yTJhWhg"/>
|
||||
<element xmi:type="uml:Transition" href="simple-history-default.uml#_Vg8HMAf7EeayEI1yTJhWhg"/>
|
||||
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_VhKJogf7EeayEI1yTJhWhg" points="[9, 0, -130, -13]$[130, 12, -9, -1]"/>
|
||||
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_VhwmkAf7EeayEI1yTJhWhg" id="(1.0,0.5)"/>
|
||||
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_VhwmkQf7EeayEI1yTJhWhg" id="(0.0,0.46808510638297873)"/>
|
||||
</edges>
|
||||
</notation:Diagram>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_T1LJ4APSEeaXyaQL1WyV3A" name="RootElement">
|
||||
<packagedElement xmi:type="uml:StateMachine" xmi:id="_T1M_EAPSEeaXyaQL1WyV3A" name="StateMachine">
|
||||
<region xmi:type="uml:Region" xmi:id="_T1NmIAPSEeaXyaQL1WyV3A" name="Region1">
|
||||
<transition xmi:type="uml:Transition" xmi:id="_tSsGEAPSEeaXyaQL1WyV3A" source="_phoPQAPSEeaXyaQL1WyV3A" target="_e85FMAPSEeaXyaQL1WyV3A"/>
|
||||
<transition xmi:type="uml:Transition" xmi:id="_vV1CgAPSEeaXyaQL1WyV3A" source="_e85FMAPSEeaXyaQL1WyV3A" target="_hkTzYAPSEeaXyaQL1WyV3A">
|
||||
<trigger xmi:type="uml:Trigger" xmi:id="_fO2icAPTEeaXyaQL1WyV3A" event="_TnRbUAPTEeaXyaQL1WyV3A"/>
|
||||
</transition>
|
||||
<transition xmi:type="uml:Transition" xmi:id="_DEzHgAPTEeaXyaQL1WyV3A" source="_e85FMAPSEeaXyaQL1WyV3A" target="_9MnMIAPSEeaXyaQL1WyV3A">
|
||||
<trigger xmi:type="uml:Trigger" xmi:id="_x7luYAPTEeaXyaQL1WyV3A" event="_aUT7EAPTEeaXyaQL1WyV3A"/>
|
||||
</transition>
|
||||
<transition xmi:type="uml:Transition" xmi:id="_Jr4JMAPTEeaXyaQL1WyV3A" source="_hkTzYAPSEeaXyaQL1WyV3A" target="_e85FMAPSEeaXyaQL1WyV3A">
|
||||
<trigger xmi:type="uml:Trigger" xmi:id="_uX4XEAPTEeaXyaQL1WyV3A" event="_YBCQ4APTEeaXyaQL1WyV3A"/>
|
||||
</transition>
|
||||
<subvertex xmi:type="uml:State" xmi:id="_e85FMAPSEeaXyaQL1WyV3A" name="S1"/>
|
||||
<subvertex xmi:type="uml:State" xmi:id="_hkTzYAPSEeaXyaQL1WyV3A" name="S2">
|
||||
<region xmi:type="uml:Region" xmi:id="_kZ9K0gPSEeaXyaQL1WyV3A" name="Region1">
|
||||
<transition xmi:type="uml:Transition" xmi:id="_xIeE0APSEeaXyaQL1WyV3A" source="_kZ-Y8APSEeaXyaQL1WyV3A" target="_kxNNMAPSEeaXyaQL1WyV3A">
|
||||
<trigger xmi:type="uml:Trigger" xmi:id="_rl-QIAPTEeaXyaQL1WyV3A" event="_VwZD8APTEeaXyaQL1WyV3A"/>
|
||||
</transition>
|
||||
<transition xmi:type="uml:Transition" xmi:id="_2k8UkAPSEeaXyaQL1WyV3A" source="_yTlNEAPSEeaXyaQL1WyV3A" target="_kZ-Y8APSEeaXyaQL1WyV3A"/>
|
||||
<transition xmi:type="uml:Transition" xmi:id="_Vg8HMAf7EeayEI1yTJhWhg" source="_9MnMIAPSEeaXyaQL1WyV3A" target="_Rq5CsAf7EeayEI1yTJhWhg"/>
|
||||
<subvertex xmi:type="uml:State" xmi:id="_kZ-Y8APSEeaXyaQL1WyV3A" name="S20"/>
|
||||
<subvertex xmi:type="uml:State" xmi:id="_kxNNMAPSEeaXyaQL1WyV3A" name="S21"/>
|
||||
<subvertex xmi:type="uml:Pseudostate" xmi:id="_yTlNEAPSEeaXyaQL1WyV3A"/>
|
||||
<subvertex xmi:type="uml:Pseudostate" xmi:id="_9MnMIAPSEeaXyaQL1WyV3A" name="SH" kind="shallowHistory"/>
|
||||
<subvertex xmi:type="uml:State" xmi:id="_Rq5CsAf7EeayEI1yTJhWhg" name="S22"/>
|
||||
</region>
|
||||
</subvertex>
|
||||
<subvertex xmi:type="uml:Pseudostate" xmi:id="_phoPQAPSEeaXyaQL1WyV3A"/>
|
||||
</region>
|
||||
</packagedElement>
|
||||
<packagedElement xmi:type="uml:Signal" xmi:id="_Ly45AAPTEeaXyaQL1WyV3A" name="E1"/>
|
||||
<packagedElement xmi:type="uml:Signal" xmi:id="_NAAzcAPTEeaXyaQL1WyV3A" name="E2"/>
|
||||
<packagedElement xmi:type="uml:Signal" xmi:id="_OI_0wAPTEeaXyaQL1WyV3A" name="E3"/>
|
||||
<packagedElement xmi:type="uml:Signal" xmi:id="_SaNyUAPTEeaXyaQL1WyV3A" name="E4"/>
|
||||
<packagedElement xmi:type="uml:SignalEvent" xmi:id="_TnRbUAPTEeaXyaQL1WyV3A" name="SignalEventE1" signal="_Ly45AAPTEeaXyaQL1WyV3A"/>
|
||||
<packagedElement xmi:type="uml:SignalEvent" xmi:id="_VwZD8APTEeaXyaQL1WyV3A" name="SignalEventE2" signal="_NAAzcAPTEeaXyaQL1WyV3A"/>
|
||||
<packagedElement xmi:type="uml:SignalEvent" xmi:id="_YBCQ4APTEeaXyaQL1WyV3A" name="SignalEventE3" signal="_OI_0wAPTEeaXyaQL1WyV3A"/>
|
||||
<packagedElement xmi:type="uml:SignalEvent" xmi:id="_aUT7EAPTEeaXyaQL1WyV3A" name="SignalEventE4" signal="_SaNyUAPTEeaXyaQL1WyV3A"/>
|
||||
</uml:Model>
|
||||
Reference in New Issue
Block a user