Add choice state support for uml model

- Relates to #193
This commit is contained in:
Janne Valkealahti
2016-04-16 12:24:58 +01:00
parent 3c7edd433e
commit 78391822a9
5 changed files with 353 additions and 1 deletions

View File

@@ -17,12 +17,18 @@ package org.springframework.statemachine.uml;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.uml2.uml.Activity;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Event;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.PackageableElement;
import org.eclipse.uml2.uml.Pseudostate;
import org.eclipse.uml2.uml.PseudostateKind;
@@ -36,6 +42,7 @@ import org.eclipse.uml2.uml.Trigger;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.Vertex;
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.StateData;
@@ -43,6 +50,7 @@ import org.springframework.statemachine.config.model.StateMachineComponentResolv
import org.springframework.statemachine.config.model.StatesData;
import org.springframework.statemachine.config.model.TransitionData;
import org.springframework.statemachine.config.model.TransitionsData;
import org.springframework.statemachine.guard.Guard;
import org.springframework.statemachine.state.PseudoStateKind;
import org.springframework.util.Assert;
@@ -60,6 +68,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 Map<String, LinkedList<ChoiceData<String, String>>> choices = new HashMap<String, LinkedList<ChoiceData<String,String>>>();
/**
* Instantiates a new uml model parser.
@@ -90,12 +99,16 @@ public class UmlModelParser {
for (Region region : stateMachine.getRegions()) {
handleRegion(region);
}
return new DataHolder(new StatesData<>(stateDatas), new TransitionsData<String, String>(transitionDatas, null, null, null, entrys, exits));
// LinkedList can be passed due to generics, need to copy
HashMap<String, List<ChoiceData<String, String>>> choicesCopy = new HashMap<String, List<ChoiceData<String,String>>>();
choicesCopy.putAll(choices);
return new DataHolder(new StatesData<>(stateDatas), new TransitionsData<String, String>(transitionDatas, choicesCopy, null, null, entrys, exits));
}
private void handleRegion(Region region) {
// build states
for (Vertex vertex : region.getSubvertices()) {
// normal states
if (vertex instanceof State) {
State state = (State)vertex;
// find parent state if submachine state, root states have null parent
@@ -134,6 +147,23 @@ public class UmlModelParser {
handleRegion(sub);
}
}
// pseudostates like choice, etc
if (vertex instanceof Pseudostate) {
Pseudostate state = (Pseudostate)vertex;
String parent = null;
String regionId = null;
if (state.getContainer().getOwner() instanceof State) {
parent = ((State)state.getContainer().getOwner()).getName();
}
if (state.getOwner() instanceof Region) {
regionId = ((Region)state.getOwner()).getName();
}
if (state.getKind() == PseudostateKind.CHOICE_LITERAL) {
StateData<String, String> cpStateData = new StateData<>(parent, regionId, state.getName(), false);
cpStateData.setPseudoStateKind(PseudoStateKind.CHOICE);
stateDatas.add(cpStateData);
}
}
}
// build transitions
@@ -149,6 +179,27 @@ public class UmlModelParser {
entrys.add(new EntryData<String, String>(transition.getSource().getName(), transition.getTarget().getName()));
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.EXIT_POINT_LITERAL) {
exits.add(new ExitData<String, String>(transition.getSource().getName(), transition.getTarget().getName()));
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.CHOICE_LITERAL) {
LinkedList<ChoiceData<String, String>> list = choices.get(transition.getSource().getName());
if (list == null) {
list = new LinkedList<ChoiceData<String, String>>();
choices.put(transition.getSource().getName(), list);
}
Guard<String, String> guard = null;
for (Constraint c : transition.getOwnedRules()) {
if (c.getSpecification() instanceof OpaqueExpression) {
OpaqueExpression oe = (OpaqueExpression)c.getSpecification();
if (oe.getBodies().size() == 1) {
guard = resolver.resolveGuard(oe.getBodies().get(0).trim());
}
}
}
// we want null guards to be at the end
if (guard == null) {
list.addLast(new ChoiceData<String, String>(transition.getSource().getName(), transition.getTarget().getName(), guard));
} else {
list.addFirst(new ChoiceData<String, String>(transition.getSource().getName(), transition.getTarget().getName(), guard));
}
}
}

View File

@@ -32,6 +32,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.action.Action;
@@ -41,7 +42,9 @@ import org.springframework.statemachine.config.builders.StateMachineModelConfigu
import org.springframework.statemachine.config.model.StateData;
import org.springframework.statemachine.config.model.StateMachineModel;
import org.springframework.statemachine.config.model.StateMachineModelFactory;
import org.springframework.statemachine.guard.Guard;
import org.springframework.statemachine.state.PseudoStateKind;
import org.springframework.util.ObjectUtils;
public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
@@ -257,6 +260,42 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S4"));
}
@Test
@SuppressWarnings("unchecked")
public void testSimpleChoice1() {
context.register(Config6.class);
context.refresh();
StateMachine<String, String> stateMachine = context.getBean(StateMachine.class);
stateMachine.start();
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1"));
stateMachine.sendEvent(MessageBuilder.withPayload("E1").setHeader("choice", "s2").build());
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S2"));
}
@Test
@SuppressWarnings("unchecked")
public void testSimpleChoice2() {
context.register(Config6.class);
context.refresh();
StateMachine<String, String> stateMachine = context.getBean(StateMachine.class);
stateMachine.start();
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1"));
stateMachine.sendEvent(MessageBuilder.withPayload("E1").setHeader("choice", "s3").build());
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S3"));
}
@Test
@SuppressWarnings("unchecked")
public void testSimpleChoice3() {
context.register(Config6.class);
context.refresh();
StateMachine<String, String> stateMachine = context.getBean(StateMachine.class);
stateMachine.start();
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1"));
stateMachine.sendEvent("E1");
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S4"));
}
@Configuration
@EnableStateMachine
public static class Config2 extends StateMachineConfigurerAdapter<String, String> {
@@ -334,6 +373,34 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
}
}
@Configuration
@EnableStateMachine
public static class Config6 extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
model
.withModel()
.factory(modelFactory());
}
@Bean
public StateMachineModelFactory<String, String> modelFactory() {
Resource model = new ClassPathResource("org/springframework/statemachine/uml/simple-choice.uml");
return new UmlStateMachineModelFactory(model);
}
@Bean
public ChoiceGuard s2Guard() {
return new ChoiceGuard("s2");
}
@Bean
public ChoiceGuard s3Guard() {
return new ChoiceGuard("s3");
}
}
public static class LatchAction implements Action<String, String> {
CountDownLatch latch = new CountDownLatch(1);
@Override
@@ -341,4 +408,19 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
latch.countDown();
}
}
private static class ChoiceGuard implements Guard<String, String> {
private final String match;
public ChoiceGuard(String match) {
this.match = match;
}
@Override
public boolean evaluate(StateContext<String, String> context) {
return ObjectUtils.nullSafeEquals(match, context.getMessageHeaders().get("choice", String.class));
}
}
}

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"/>

View File

@@ -0,0 +1,181 @@
<?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="_OrqPAAOpEeaiNLSABY7wHw" type="PapyrusUMLStateMachineDiagram" name="StateMachine Diagram" measurementUnit="Pixel">
<children xmi:type="notation:Shape" xmi:id="_OrqPAQOpEeaiNLSABY7wHw" type="2000">
<children xmi:type="notation:DecorationNode" xmi:id="_OrqPAgOpEeaiNLSABY7wHw" type="2001">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrqPAwOpEeaiNLSABY7wHw" width="700" height="23"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_OrqPBAOpEeaiNLSABY7wHw" type="2002">
<children xmi:type="notation:Shape" xmi:id="_OrqPBQOpEeaiNLSABY7wHw" type="3000">
<eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_OrqPBgOpEeaiNLSABY7wHw" source="RegionAnnotationKey">
<details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_OrqPBwOpEeaiNLSABY7wHw" key="RegionZoneKey" value=""/>
</eAnnotations>
<children xmi:type="notation:DecorationNode" xmi:id="_OrqPCAOpEeaiNLSABY7wHw" type="3002">
<children xmi:type="notation:Shape" xmi:id="_e6i4cAOpEeaiNLSABY7wHw" type="6000">
<children xmi:type="notation:DecorationNode" xmi:id="_e6i4cgOpEeaiNLSABY7wHw" type="6001">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_kOQNwAOpEeaiNLSABY7wHw" width="83"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_e6jfgAOpEeaiNLSABY7wHw" type="19003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_e6jfgQOpEeaiNLSABY7wHw" x="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_e6jfggOpEeaiNLSABY7wHw" type="6002">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_e6jfgwOpEeaiNLSABY7wHw" y="-1" width="83"/>
</children>
<element xmi:type="uml:State" href="simple-choice.uml#_e6aVkAOpEeaiNLSABY7wHw"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_e6i4cQOpEeaiNLSABY7wHw" x="110" y="107" width="83"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_fyMSIAOpEeaiNLSABY7wHw" type="8000">
<children xmi:type="notation:DecorationNode" xmi:id="_fyM5MAOpEeaiNLSABY7wHw" type="8001">
<layoutConstraint xmi:type="notation:Location" xmi:id="_fyM5MQOpEeaiNLSABY7wHw" x="25" y="3"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_fyM5MgOpEeaiNLSABY7wHw" type="8002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_fyM5MwOpEeaiNLSABY7wHw" x="25" y="-10"/>
</children>
<element xmi:type="uml:Pseudostate" href="simple-choice.uml#_fyGykAOpEeaiNLSABY7wHw"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_fyMSIQOpEeaiNLSABY7wHw" x="30" y="107"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_hTbbYAOpEeaiNLSABY7wHw" type="6000">
<children xmi:type="notation:DecorationNode" xmi:id="_hTbbYgOpEeaiNLSABY7wHw" type="6001">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_ln3FAAOpEeaiNLSABY7wHw" width="83"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_hTbbYwOpEeaiNLSABY7wHw" type="19003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_hTbbZAOpEeaiNLSABY7wHw" x="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_hTbbZQOpEeaiNLSABY7wHw" type="6002">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_hTbbZgOpEeaiNLSABY7wHw" y="-1" width="83"/>
</children>
<element xmi:type="uml:State" href="simple-choice.uml#_hTUGoAOpEeaiNLSABY7wHw"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_hTbbYQOpEeaiNLSABY7wHw" x="490" y="27" width="83"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_hwzT4AOpEeaiNLSABY7wHw" type="6000">
<children xmi:type="notation:DecorationNode" xmi:id="_hwzT4gOpEeaiNLSABY7wHw" type="6001">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_ln3sEAOpEeaiNLSABY7wHw" width="83"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_hwzT4wOpEeaiNLSABY7wHw" type="19003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_hwzT5AOpEeaiNLSABY7wHw" x="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_hwzT5QOpEeaiNLSABY7wHw" type="6002">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_hwzT5gOpEeaiNLSABY7wHw" y="-1" width="83"/>
</children>
<element xmi:type="uml:State" href="simple-choice.uml#_hwr_IAOpEeaiNLSABY7wHw"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_hwzT4QOpEeaiNLSABY7wHw" x="490" y="127" width="83"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_in_akAOpEeaiNLSABY7wHw" type="11000">
<children xmi:type="notation:DecorationNode" xmi:id="_ioABoAOpEeaiNLSABY7wHw" type="11001">
<layoutConstraint xmi:type="notation:Location" xmi:id="_ioABoQOpEeaiNLSABY7wHw" x="-20" y="-20"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_ioABogOpEeaiNLSABY7wHw" type="11002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_ioABowOpEeaiNLSABY7wHw" x="25" y="-10"/>
</children>
<element xmi:type="uml:Pseudostate" href="simple-choice.uml#_in3ewAOpEeaiNLSABY7wHw"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_in_akQOpEeaiNLSABY7wHw" x="250" y="107"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_1gApcAOpEeaiNLSABY7wHw" type="6000">
<children xmi:type="notation:DecorationNode" xmi:id="_1gBQgAOpEeaiNLSABY7wHw" type="6001">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_3uzcQAOpEeaiNLSABY7wHw" width="83"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_1gBQgQOpEeaiNLSABY7wHw" type="19003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_1gBQggOpEeaiNLSABY7wHw" x="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_1gBQgwOpEeaiNLSABY7wHw" type="6002">
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_1gBQhAOpEeaiNLSABY7wHw" y="-1" width="83"/>
</children>
<element xmi:type="uml:State" href="simple-choice.uml#_1f3fgAOpEeaiNLSABY7wHw"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_1gApcQOpEeaiNLSABY7wHw" x="490" y="227" width="83"/>
</children>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrqPCQOpEeaiNLSABY7wHw"/>
</children>
<element xmi:type="uml:Region" href="simple-choice.uml#_OrpA4AOpEeaiNLSABY7wHw"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrqPCgOpEeaiNLSABY7wHw" width="700" height="287"/>
</children>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrqPCwOpEeaiNLSABY7wHw" y="23" width="700" height="287"/>
</children>
<element xmi:type="uml:StateMachine" href="simple-choice.uml#_OrcMkAOpEeaiNLSABY7wHw"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrqPDAOpEeaiNLSABY7wHw" x="30" y="30" width="700" height="310"/>
</children>
<styles xmi:type="notation:StringValueStyle" xmi:id="_OrqPDQOpEeaiNLSABY7wHw" name="diagram_compatibility_version" stringValue="1.1.0"/>
<styles xmi:type="notation:DiagramStyle" xmi:id="_OrqPDgOpEeaiNLSABY7wHw"/>
<styles xmi:type="style:PapyrusViewStyle" xmi:id="_OrqPDwOpEeaiNLSABY7wHw">
<owner xmi:type="uml:Model" href="simple-choice.uml#_OqqwgAOpEeaiNLSABY7wHw"/>
</styles>
<element xmi:type="uml:StateMachine" href="simple-choice.uml#_OrcMkAOpEeaiNLSABY7wHw"/>
<edges xmi:type="notation:Connector" xmi:id="_7ZbT4AOpEeaiNLSABY7wHw" type="7000" source="_fyMSIAOpEeaiNLSABY7wHw" target="_e6i4cAOpEeaiNLSABY7wHw">
<children xmi:type="notation:DecorationNode" xmi:id="_7Zb68AOpEeaiNLSABY7wHw" type="7001">
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Zb68QOpEeaiNLSABY7wHw"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_7Zb68gOpEeaiNLSABY7wHw" type="7002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Zb68wOpEeaiNLSABY7wHw"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_7Zb69AOpEeaiNLSABY7wHw" type="7003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Zb69QOpEeaiNLSABY7wHw" y="60"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_7ZbT4QOpEeaiNLSABY7wHw"/>
<element xmi:type="uml:Transition" href="simple-choice.uml#_7V6s4AOpEeaiNLSABY7wHw"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_7ZbT4gOpEeaiNLSABY7wHw" points="[8, -4, -123, 0]$[130, -10, -1, -6]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_7aHQYAOpEeaiNLSABY7wHw" id="(1.0,0.5)"/>
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_7aH3cAOpEeaiNLSABY7wHw" id="(0.0,0.14893617021276595)"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_X0QVwAOqEeaiNLSABY7wHw" type="7000" source="_e6i4cAOpEeaiNLSABY7wHw" target="_in_akAOpEeaiNLSABY7wHw">
<children xmi:type="notation:DecorationNode" xmi:id="_X0Q80AOqEeaiNLSABY7wHw" type="7001">
<layoutConstraint xmi:type="notation:Location" xmi:id="_X0Q80QOqEeaiNLSABY7wHw"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_X0Q80gOqEeaiNLSABY7wHw" type="7002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_X0Q80wOqEeaiNLSABY7wHw" x="10" y="17"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_X0Q81AOqEeaiNLSABY7wHw" type="7003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_X0Q81QOqEeaiNLSABY7wHw" y="60"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_X0QVwQOqEeaiNLSABY7wHw"/>
<element xmi:type="uml:Transition" href="simple-choice.uml#_X0EvkAOqEeaiNLSABY7wHw"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_X0QVwgOqEeaiNLSABY7wHw" points="[5, 0, -89, -10]$[86, 10, -8, 0]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_X0wsEAOqEeaiNLSABY7wHw" id="(1.0,0.44680851063829785)"/>
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_X0wsEQOqEeaiNLSABY7wHw" id="(0.0,0.45)"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_ar9isAOqEeaiNLSABY7wHw" type="7000" source="_in_akAOpEeaiNLSABY7wHw" target="_hTbbYAOpEeaiNLSABY7wHw">
<children xmi:type="notation:DecorationNode" xmi:id="_ar-JwAOqEeaiNLSABY7wHw" type="7001">
<layoutConstraint xmi:type="notation:Location" xmi:id="_ar-JwQOqEeaiNLSABY7wHw"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_ar-JwgOqEeaiNLSABY7wHw" type="7002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_ar-JwwOqEeaiNLSABY7wHw" x="-15" y="-29"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_ar-JxAOqEeaiNLSABY7wHw" type="7003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_ar-JxQOqEeaiNLSABY7wHw" y="60"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_ar9isQOqEeaiNLSABY7wHw"/>
<element xmi:type="uml:Transition" href="simple-choice.uml#_arx8gAOqEeaiNLSABY7wHw"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_ar9isgOqEeaiNLSABY7wHw" points="[10, -7, -100, 83]$[113, -88, 3, 2]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_ascq4AOqEeaiNLSABY7wHw" id="(0.9,0.0)"/>
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_ascq4QOqEeaiNLSABY7wHw" id="(0.0,0.5319148936170213)"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_bfppcAOqEeaiNLSABY7wHw" type="7000" source="_in_akAOpEeaiNLSABY7wHw" target="_hwzT4AOpEeaiNLSABY7wHw">
<children xmi:type="notation:DecorationNode" xmi:id="_bfppcwOqEeaiNLSABY7wHw" type="7001">
<layoutConstraint xmi:type="notation:Location" xmi:id="_bfppdAOqEeaiNLSABY7wHw"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_bfppdQOqEeaiNLSABY7wHw" type="7002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_bfppdgOqEeaiNLSABY7wHw" x="10" y="-22"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_bfqQgAOqEeaiNLSABY7wHw" type="7003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_bfqQgQOqEeaiNLSABY7wHw" y="60"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_bfppcQOqEeaiNLSABY7wHw"/>
<element xmi:type="uml:Transition" href="simple-choice.uml#_bfbnAAOqEeaiNLSABY7wHw"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_bfppcgOqEeaiNLSABY7wHw" points="[20, 3, -90, 13]$[144, 37, 34, 47]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_bgNqIAOqEeaiNLSABY7wHw" id="(1.0,0.75)"/>
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_bgNqIQOqEeaiNLSABY7wHw" id="(0.0,0.574468085106383)"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_cJG2IAOqEeaiNLSABY7wHw" type="7000" source="_in_akAOpEeaiNLSABY7wHw" target="_1gApcAOpEeaiNLSABY7wHw">
<children xmi:type="notation:DecorationNode" xmi:id="_cJG2IwOqEeaiNLSABY7wHw" type="7001">
<layoutConstraint xmi:type="notation:Location" xmi:id="_cJHdMAOqEeaiNLSABY7wHw"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_cJHdMQOqEeaiNLSABY7wHw" type="7002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_cJHdMgOqEeaiNLSABY7wHw"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_cJHdMwOqEeaiNLSABY7wHw" type="7003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_cJHdNAOqEeaiNLSABY7wHw" y="60"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_cJG2IQOqEeaiNLSABY7wHw"/>
<element xmi:type="uml:Transition" href="simple-choice.uml#_cIytEAOqEeaiNLSABY7wHw"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_cJG2IgOqEeaiNLSABY7wHw" points="[10, 6, -114, -76]$[110, 76, -14, -6]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_cJvIQAOqEeaiNLSABY7wHw" id="(0.6833333333333333,1.0)"/>
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_cJvvUAOqEeaiNLSABY7wHw" id="(0.0,0.06382978723404255)"/>
</edges>
</notation:Diagram>

View File

@@ -0,0 +1,36 @@
<?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="_OqqwgAOpEeaiNLSABY7wHw" name="RootElement">
<packagedElement xmi:type="uml:StateMachine" xmi:id="_OrcMkAOpEeaiNLSABY7wHw" name="StateMachine">
<region xmi:type="uml:Region" xmi:id="_OrpA4AOpEeaiNLSABY7wHw" name="Region1">
<transition xmi:type="uml:Transition" xmi:id="_7V6s4AOpEeaiNLSABY7wHw" source="_fyGykAOpEeaiNLSABY7wHw" target="_e6aVkAOpEeaiNLSABY7wHw"/>
<transition xmi:type="uml:Transition" xmi:id="_X0EvkAOqEeaiNLSABY7wHw" source="_e6aVkAOpEeaiNLSABY7wHw" target="_in3ewAOpEeaiNLSABY7wHw">
<trigger xmi:type="uml:Trigger" xmi:id="_CVbtoAOzEeaiNLSABY7wHw" event="_9sMRoAOyEeaiNLSABY7wHw"/>
</transition>
<transition xmi:type="uml:Transition" xmi:id="_arx8gAOqEeaiNLSABY7wHw" guard="_yT_ckAOtEeaiNLSABY7wHw" source="_in3ewAOpEeaiNLSABY7wHw" target="_hTUGoAOpEeaiNLSABY7wHw">
<ownedRule xmi:type="uml:Constraint" xmi:id="_yT_ckAOtEeaiNLSABY7wHw">
<specification xmi:type="uml:OpaqueExpression" xmi:id="_yT_ckQOtEeaiNLSABY7wHw">
<language>bean</language>
<body>s2Guard</body>
</specification>
</ownedRule>
</transition>
<transition xmi:type="uml:Transition" xmi:id="_bfbnAAOqEeaiNLSABY7wHw" guard="_9yVIIAOtEeaiNLSABY7wHw" source="_in3ewAOpEeaiNLSABY7wHw" target="_hwr_IAOpEeaiNLSABY7wHw">
<ownedRule xmi:type="uml:Constraint" xmi:id="_9yVIIAOtEeaiNLSABY7wHw">
<specification xmi:type="uml:OpaqueExpression" xmi:id="_9yVIIQOtEeaiNLSABY7wHw">
<language>bean</language>
<body>s3Guard</body>
</specification>
</ownedRule>
</transition>
<transition xmi:type="uml:Transition" xmi:id="_cIytEAOqEeaiNLSABY7wHw" source="_in3ewAOpEeaiNLSABY7wHw" target="_1f3fgAOpEeaiNLSABY7wHw"/>
<subvertex xmi:type="uml:State" xmi:id="_e6aVkAOpEeaiNLSABY7wHw" name="S1"/>
<subvertex xmi:type="uml:Pseudostate" xmi:id="_fyGykAOpEeaiNLSABY7wHw"/>
<subvertex xmi:type="uml:State" xmi:id="_hTUGoAOpEeaiNLSABY7wHw" name="S2"/>
<subvertex xmi:type="uml:State" xmi:id="_hwr_IAOpEeaiNLSABY7wHw" name="S3"/>
<subvertex xmi:type="uml:Pseudostate" xmi:id="_in3ewAOpEeaiNLSABY7wHw" name="CHOICE" kind="choice"/>
<subvertex xmi:type="uml:State" xmi:id="_1f3fgAOpEeaiNLSABY7wHw" name="S4"/>
</region>
</packagedElement>
<packagedElement xmi:type="uml:Signal" xmi:id="_61ApIAOyEeaiNLSABY7wHw" name="E1"/>
<packagedElement xmi:type="uml:SignalEvent" xmi:id="_9sMRoAOyEeaiNLSABY7wHw" name="SignalEventE1" signal="_61ApIAOyEeaiNLSABY7wHw"/>
</uml:Model>