Allow auto naming for uml pseudostates

- Fixing issue when i.e. choice pseudostate is not named which
  then cause some other internal errors in a model parser.
- As pseudostate need to have a name, we now auto generate with
  pseudostate type name + counter.
- Fixes #591
This commit is contained in:
Janne Valkealahti
2019-01-13 16:09:25 +00:00
parent b30f0ed0b3
commit d698fc8d11
5 changed files with 319 additions and 40 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2018 the original author or authors.
* Copyright 2016-2019 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.
@@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;
@@ -29,6 +30,7 @@ import org.eclipse.uml2.uml.ConnectionPointReference;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Event;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.OpaqueBehavior;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.PackageableElement;
@@ -63,6 +65,7 @@ import org.springframework.statemachine.guard.Guard;
import org.springframework.statemachine.guard.SpelExpressionGuard;
import org.springframework.statemachine.state.PseudoStateKind;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -87,6 +90,9 @@ public class UmlModelParser {
private final Map<String, List<String>> forks = new HashMap<String, List<String>>();
private final Map<String, List<String>> joins = new HashMap<String, List<String>>();
private final AtomicInteger pseudostateNamingCounter = new AtomicInteger(1);
private final Map<NamedElement, String> pseudostateNaming = new HashMap<>();
/**
* Instantiates a new uml model parser.
*
@@ -140,6 +146,18 @@ public class UmlModelParser {
}
}
private String resolveName(NamedElement pseudostate) {
return pseudostateNaming.computeIfAbsent(pseudostate, key -> {
String name = pseudostate.getName();
if (ObjectUtils.isEmpty(name)) {
if (key instanceof Pseudostate) {
name = ((Pseudostate)key).getKind().getName() + pseudostateNamingCounter.getAndIncrement();
}
}
return name;
});
}
private void handleRegion(Region region) {
// build states
for (Vertex vertex : region.getSubvertices()) {
@@ -226,7 +244,7 @@ public class UmlModelParser {
regionId = ((Region)state.getOwner()).getName();
}
if (state.getKind() == PseudostateKind.CHOICE_LITERAL) {
StateData<String, String> cpStateData = new StateData<>(parent, regionId, state.getName(), false);
StateData<String, String> cpStateData = new StateData<>(parent, regionId, resolveName(state), false);
cpStateData.setPseudoStateKind(PseudoStateKind.CHOICE);
stateDatas.add(cpStateData);
} else if (state.getKind() == PseudostateKind.JUNCTION_LITERAL) {
@@ -268,68 +286,68 @@ public class UmlModelParser {
// realistic with state machines
EList<Pseudostate> cprentries = ((ConnectionPointReference)transition.getSource()).getEntries();
if (cprentries != null && cprentries.size() == 1 && cprentries.get(0).getKind() == PseudostateKind.ENTRY_POINT_LITERAL) {
entrys.add(new EntryData<String, String>(cprentries.get(0).getName(), transition.getTarget().getName()));
entrys.add(new EntryData<String, String>(cprentries.get(0).getName(), resolveName(transition.getTarget())));
}
EList<Pseudostate> cprexits = ((ConnectionPointReference)transition.getSource()).getExits();
if (cprexits != null && cprexits.size() == 1 && cprexits.get(0).getKind() == PseudostateKind.EXIT_POINT_LITERAL) {
exits.add(new ExitData<String, String>(cprexits.get(0).getName(), transition.getTarget().getName()));
exits.add(new ExitData<String, String>(cprexits.get(0).getName(), resolveName(transition.getTarget())));
}
}
if (transition.getSource() instanceof Pseudostate) {
if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.ENTRY_POINT_LITERAL) {
entrys.add(new EntryData<String, String>(transition.getSource().getName(), transition.getTarget().getName()));
entrys.add(new EntryData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget())));
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.EXIT_POINT_LITERAL) {
exits.add(new ExitData<String, String>(transition.getSource().getName(), transition.getTarget().getName()));
exits.add(new ExitData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget())));
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.CHOICE_LITERAL) {
LinkedList<ChoiceData<String, String>> list = choices.get(transition.getSource().getName());
LinkedList<ChoiceData<String, String>> list = choices.get(resolveName(transition.getSource()));
if (list == null) {
list = new LinkedList<ChoiceData<String, String>>();
choices.put(transition.getSource().getName(), list);
choices.put(resolveName(transition.getSource()), list);
}
Guard<String, String> guard = resolveGuard(transition);
Collection<Action<String,String>> actions = UmlUtils.resolveTransitionActions(transition, resolver);
// 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, actions));
list.addLast(new ChoiceData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget()), guard, actions));
} else {
list.addFirst(new ChoiceData<String, String>(transition.getSource().getName(), transition.getTarget().getName(), guard, actions));
list.addFirst(new ChoiceData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget()), guard, actions));
}
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.JUNCTION_LITERAL) {
LinkedList<JunctionData<String, String>> list = junctions.get(transition.getSource().getName());
LinkedList<JunctionData<String, String>> list = junctions.get(resolveName(transition.getSource()));
if (list == null) {
list = new LinkedList<JunctionData<String, String>>();
junctions.put(transition.getSource().getName(), list);
junctions.put(resolveName(transition.getSource()), list);
}
Guard<String, String> guard = resolveGuard(transition);
Collection<Action<String,String>> actions = UmlUtils.resolveTransitionActions(transition, resolver);
// we want null guards to be at the end
if (guard == null) {
list.addLast(new JunctionData<String, String>(transition.getSource().getName(), transition.getTarget().getName(), guard, actions));
list.addLast(new JunctionData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget()), guard, actions));
} else {
list.addFirst(new JunctionData<String, String>(transition.getSource().getName(), transition.getTarget().getName(), guard, actions));
list.addFirst(new JunctionData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget()), guard, actions));
}
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.FORK_LITERAL) {
List<String> list = forks.get(transition.getSource().getName());
List<String> list = forks.get(resolveName(transition.getSource()));
if (list == null) {
list = new ArrayList<String>();
forks.put(transition.getSource().getName(), list);
forks.put(resolveName(transition.getSource()), list);
}
list.add(transition.getTarget().getName());
list.add(resolveName(transition.getTarget()));
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.SHALLOW_HISTORY_LITERAL) {
historys.add(new HistoryData<String, String>(transition.getSource().getName(), transition.getTarget().getName()));
historys.add(new HistoryData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget())));
} else if (((Pseudostate)transition.getSource()).getKind() == PseudostateKind.DEEP_HISTORY_LITERAL) {
historys.add(new HistoryData<String, String>(transition.getSource().getName(), transition.getTarget().getName()));
historys.add(new HistoryData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget())));
}
}
if (transition.getTarget() instanceof Pseudostate) {
if (((Pseudostate)transition.getTarget()).getKind() == PseudostateKind.JOIN_LITERAL) {
List<String> list = joins.get(transition.getTarget().getName());
List<String> list = joins.get(resolveName(transition.getTarget()));
if (list == null) {
list = new ArrayList<String>();
joins.put(transition.getTarget().getName(), list);
joins.put(resolveName(transition.getTarget()), list);
}
list.add(transition.getSource().getName());
list.add(resolveName(transition.getSource()));
}
}
@@ -345,13 +363,13 @@ public class UmlModelParser {
if (transition.getTarget() instanceof ConnectionPointReference) {
EList<Pseudostate> cprentries = ((ConnectionPointReference)transition.getTarget()).getEntries();
if (cprentries != null && cprentries.size() == 1) {
transitionDatas.add(new TransitionData<String, String>(transition.getSource().getName(),
transitionDatas.add(new TransitionData<String, String>(resolveName(transition.getSource()),
cprentries.get(0).getName(), signal.getName(), UmlUtils.resolveTransitionActions(transition, resolver),
guard, UmlUtils.mapUmlTransitionType(transition)));
}
} else {
transitionDatas.add(new TransitionData<String, String>(transition.getSource().getName(),
transition.getTarget().getName(), signal.getName(), UmlUtils.resolveTransitionActions(transition, resolver),
transitionDatas.add(new TransitionData<String, String>(resolveName(transition.getSource()),
resolveName(transition.getTarget()), signal.getName(), UmlUtils.resolveTransitionActions(transition, resolver),
guard, UmlUtils.mapUmlTransitionType(transition)));
}
}
@@ -363,8 +381,8 @@ public class UmlModelParser {
if (timeEvent.isRelative()) {
count = 1;
}
transitionDatas.add(new TransitionData<String, String>(transition.getSource().getName(),
transition.getTarget().getName(), period, count, UmlUtils.resolveTransitionActions(transition, resolver),
transitionDatas.add(new TransitionData<String, String>(resolveName(transition.getSource()),
resolveName(transition.getTarget()), period, count, UmlUtils.resolveTransitionActions(transition, resolver),
guard, UmlUtils.mapUmlTransitionType(transition)));
}
}
@@ -372,7 +390,7 @@ public class UmlModelParser {
// create anonymous transition if needed
if (shouldCreateAnonymousTransition(transition)) {
transitionDatas.add(new TransitionData<String, String>(transition.getSource().getName(), transition.getTarget().getName(),
transitionDatas.add(new TransitionData<String, String>(resolveName(transition.getSource()), resolveName(transition.getTarget()),
null, UmlUtils.resolveTransitionActions(transition, resolver), resolveGuard(transition),
UmlUtils.mapUmlTransitionType(transition)));
}
@@ -424,10 +442,10 @@ public class UmlModelParser {
if (!transition.getTriggers().isEmpty()) {
return false;
}
if (!StringUtils.hasText(transition.getSource().getName())) {
if (!StringUtils.hasText(resolveName(transition.getSource()))) {
return false;
}
if (!StringUtils.hasText(transition.getTarget().getName())) {
if (!StringUtils.hasText(resolveName(transition.getTarget()))) {
return false;
}
if (transition.getSource() instanceof Pseudostate) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2018 the original author or authors.
* Copyright 2016-2019 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.
@@ -326,6 +326,18 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S4"));
}
@Test
@SuppressWarnings("unchecked")
public void testMissingNameChoice() {
context.register(Config6MissingName.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 testSimpleForkJoin() {
@@ -513,16 +525,18 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
Collection<StateData<String, String>> stateDatas = stateMachineModel.getStatesData().getStateData();
Collection<TransitionData<String, String>> transitionDatas = stateMachineModel.getTransitionsData().getTransitions();
assertThat(stateDatas.size(), is(2));
assertThat(transitionDatas.size(), is(3));
assertThat(transitionDatas.size(), is(4));
for (TransitionData<String, String> transitionData : transitionDatas) {
if (transitionData.getEvent().equals("E1")) {
assertThat(transitionData.getKind(), is(TransitionKind.EXTERNAL));
} else if (transitionData.getEvent().equals("E2")) {
assertThat(transitionData.getKind(), is(TransitionKind.LOCAL));
} else if (transitionData.getEvent().equals("E3")) {
assertThat(transitionData.getKind(), is(TransitionKind.INTERNAL));
} else {
throw new IllegalArgumentException();
if (transitionData.getEvent() != null) {
if (transitionData.getEvent().equals("E1")) {
assertThat(transitionData.getKind(), is(TransitionKind.EXTERNAL));
} else if (transitionData.getEvent().equals("E2")) {
assertThat(transitionData.getKind(), is(TransitionKind.LOCAL));
} else if (transitionData.getEvent().equals("E3")) {
assertThat(transitionData.getKind(), is(TransitionKind.INTERNAL));
} else {
throw new IllegalArgumentException();
}
}
}
}
@@ -1173,6 +1187,34 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests {
}
}
@Configuration
@EnableStateMachine
public static class Config6MissingName 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/missingname-choice.uml");
return new UmlStateMachineModelFactory(model);
}
@Bean
public ChoiceGuard s2Guard() {
return new ChoiceGuard("s2");
}
@Bean
public ChoiceGuard s3Guard() {
return new ChoiceGuard("s3");
}
}
@Configuration
@EnableStateMachine
public static class Config7 extends StateMachineConfigurerAdapter<String, String> {

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" 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>