Jelajahi Sumber

Merge pull request #591 from Yakindu/issue_565

Issue 565
jdicks 9 tahun lalu
induk
melakukan
15af5e9d60

+ 4 - 4
examples/traffic_light/model/TrafficLightCtrl.sgen

@@ -17,11 +17,11 @@ GeneratorModel for yakindu::java {
 			TimerService = true
 		}
 		
-		feature RunnableWrapper {
-			namePrefix =  "" 
-			nameSuffix =  "Runnable" 
+		feature SynchronizedWrapper {
+			namePrefix =  "Synchronized" 
+			nameSuffix =  "" 
 		}
-		
+				
 		feature LicenseHeader {
 			licenseText = "
 Copyright (c) 2012-2015 committers of YAKINDU and others.

+ 7 - 4
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/STextJavaValidator.java

@@ -149,10 +149,13 @@ public class STextJavaValidator extends AbstractSTextJavaValidator implements ST
 
 	@Check(CheckType.FAST)
 	public void transitionsWithNoTrigger(Transition trans) {
-		if (trans.getSource() instanceof Entry || trans.getSource() instanceof Choice
-				|| trans.getSource() instanceof Synchronization) {
-			return;
-		}
+
+		if (trans.getSource() instanceof Entry 
+			|| trans.getSource() instanceof Choice
+			|| trans.getSource() instanceof Synchronization
+			|| (trans.getTarget() instanceof Synchronization && (trans.getTarget().getIncomingTransitions().size() > 1))
+			) { return; }
+		
 		if (trans.getSource() instanceof org.yakindu.sct.model.sgraph.State) {
 			org.yakindu.sct.model.sgraph.State state = (org.yakindu.sct.model.sgraph.State) trans.getSource();
 			if (state.isComposite()) {

+ 12 - 4
test-plugins/org.yakindu.sct.model.stext.test/src/org/yakindu/sct/model/stext/test/AllTests.java

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2012 committers of YAKINDU and others.
+ * Copyright (c) 2012-2016 committers of YAKINDU and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,14 +13,22 @@ package org.yakindu.sct.model.stext.test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
 import org.junit.runners.Suite.SuiteClasses;
+import org.yakindu.sct.model.stext.test.validation.STextJavaValidatorTest;
+import org.yakindu.sct.model.stext.test.validation.TransitionsWithNoTriggerTest;
 
 /**
  * @author andreas muelder - Initial contribution and API
+ * @author terfloth - extensions
  * 
  */
 @RunWith(value = Suite.class)
-@SuiteClasses(value = { TypeInferrerTest.class, STextJavaValidatorTest.class, StextParserRuleTest.class,
-		TestModelsContainErrorsTest.class, SCTUnitClassifierTest.class })
-public class AllTests {
+@SuiteClasses(value = { 
+		TypeInferrerTest.class, 
+		StextParserRuleTest.class,
+		TestModelsContainErrorsTest.class, 
+		SCTUnitClassifierTest.class, 
+		STextJavaValidatorTest.class, 
+		TransitionsWithNoTriggerTest.class })
 
+public class AllTests {
 }

+ 106 - 0
test-plugins/org.yakindu.sct.model.stext.test/src/org/yakindu/sct/model/stext/test/validation/AbstractSTextValidationTest.java

@@ -0,0 +1,106 @@
+package org.yakindu.sct.model.stext.test.validation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.yakindu.sct.test.models.AbstractTestModelsUtil.VALIDATION_TESTMODEL_DIR;
+
+import java.util.HashMap;
+
+import org.eclipse.emf.common.util.BasicDiagnostic;
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.junit4.validation.ValidatorTester;
+import org.junit.After;
+import org.junit.Before;
+import org.yakindu.sct.model.sgraph.SGraphFactory;
+import org.yakindu.sct.model.sgraph.Statechart;
+import org.yakindu.sct.model.sgraph.Transition;
+import org.yakindu.sct.model.sgraph.Vertex;
+import org.yakindu.sct.model.stext.resource.StextResource;
+import org.yakindu.sct.model.stext.test.util.AbstractSTextTest;
+import org.yakindu.sct.model.stext.validation.STextJavaValidator;
+import org.yakindu.sct.test.models.AbstractTestModelsUtil;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+public abstract class AbstractSTextValidationTest extends AbstractSTextTest {
+
+	@Inject
+	public STextJavaValidator validator;
+	@Inject
+	public Injector injector;
+
+	protected ValidatorTester<STextJavaValidator> tester;
+	protected BasicDiagnostic diagnostics;
+	protected SGraphFactory factory;
+	protected Statechart statechart;
+	protected StextResource resource;
+
+	@Before public void setup() {
+		factory = SGraphFactory.eINSTANCE;
+	
+		resource = new StextResource(URI.createURI(""));
+		injector.injectMembers(resource);
+		statechart = factory.createStatechart();
+		resource.getContents().add(statechart);
+	
+		diagnostics = new BasicDiagnostic();
+		tester = new ValidatorTester<STextJavaValidator>(validator, injector);
+	}
+
+	@After public void teardown() {
+		tester = null;
+	}
+
+	protected void resetDiagnostics() {
+		diagnostics = new BasicDiagnostic();
+	}
+
+	protected Transition createTransition(Vertex source, Vertex target) {
+		Transition trans = SGraphFactory.eINSTANCE.createTransition();
+		trans.setSource(source);
+		trans.setTarget(target);
+		source.getOutgoingTransitions().add(trans);
+		target.getIncomingTransitions().add(trans);
+		return trans;
+	}
+
+	protected void assertError(Diagnostic diag, String message) {
+		Diagnostic d = issueByName(diag, message);
+		assertNotNull("Issue '" + message + "' does not exist.", issueByName(diag, message));
+		assertEquals("Issue '" + message + "' is no error.", Diagnostic.ERROR, d.getSeverity());
+	}
+
+	protected void assertWarning(Diagnostic diag, String message) {
+		Diagnostic d = issueByName(diag, message);
+		assertNotNull("Issue '" + message + "' does not exist.", issueByName(diag, message));
+		assertEquals("Issue '" + message + "' is no warning.", Diagnostic.WARNING, d.getSeverity());
+	}
+
+	protected void assertIssueCount(Diagnostic diag, int count) {
+		int c = diag.getChildren().size();
+		assertEquals("expected " + count + " issue(s) but were " + c + " [" + diag.toString() + "]", count, c);
+	}
+
+	protected Diagnostic issueByName(Diagnostic diag, String message) {
+		for (Diagnostic issue : diag.getChildren()) {
+			if (message.equals(issue.getMessage()))
+				return issue;
+		}
+		return null;
+	}
+
+	protected boolean validate(EObject obj) {
+		return validator.validate(obj, diagnostics,
+				new HashMap<Object, Object>());
+	}
+
+	protected Statechart loadStatechart(String modelName) {
+		return AbstractTestModelsUtil
+				.loadStatechart(VALIDATION_TESTMODEL_DIR
+						+ modelName);
+	}
+
+}

+ 8 - 187
test-plugins/org.yakindu.sct.model.stext.test/src/org/yakindu/sct/model/stext/test/STextJavaValidatorTest.java

@@ -9,10 +9,9 @@
  * 	itemis AG - initial API and implementation
  * 
  */
-package org.yakindu.sct.model.stext.test;
+package org.yakindu.sct.model.stext.test.validation;
 
 import static org.eclipse.xtext.junit4.validation.AssertableDiagnostics.errorCode;
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.yakindu.sct.test.models.AbstractTestModelsUtil.VALIDATION_TESTMODEL_DIR;
@@ -21,18 +20,13 @@ import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Iterator;
 
-import org.eclipse.emf.common.util.BasicDiagnostic;
 import org.eclipse.emf.common.util.Diagnostic;
-import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.util.Diagnostician;
 import org.eclipse.xtext.junit4.InjectWith;
 import org.eclipse.xtext.junit4.XtextRunner;
 import org.eclipse.xtext.junit4.validation.AssertableDiagnostics;
-import org.eclipse.xtext.junit4.validation.ValidatorTester;
 import org.eclipse.xtext.validation.Check;
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.yakindu.base.expressions.expressions.Expression;
@@ -40,15 +34,12 @@ import org.yakindu.sct.model.sgraph.Choice;
 import org.yakindu.sct.model.sgraph.Entry;
 import org.yakindu.sct.model.sgraph.Exit;
 import org.yakindu.sct.model.sgraph.Region;
-import org.yakindu.sct.model.sgraph.SGraphFactory;
 import org.yakindu.sct.model.sgraph.Scope;
 import org.yakindu.sct.model.sgraph.State;
 import org.yakindu.sct.model.sgraph.Statechart;
 import org.yakindu.sct.model.sgraph.Transition;
 import org.yakindu.sct.model.sgraph.Trigger;
-import org.yakindu.sct.model.sgraph.Vertex;
 import org.yakindu.sct.model.stext.inferrer.STextTypeInferrer;
-import org.yakindu.sct.model.stext.resource.StextResource;
 import org.yakindu.sct.model.stext.stext.ImportScope;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.InternalScope;
@@ -75,38 +66,8 @@ import com.google.inject.Injector;
  */
 @RunWith(XtextRunner.class)
 @InjectWith(STextInjectorProvider.class)
-public class STextJavaValidatorTest extends AbstractSTextTest implements STextValidationMessages {
-
-	@Inject
-	private STextJavaValidator validator;
-	@Inject
-	private Injector injector;
-	private ValidatorTester<STextJavaValidator> tester;
-	protected BasicDiagnostic diagnostics;
-	protected SGraphFactory factory;
-	protected Statechart statechart;
-	protected StextResource resource;
-
-	public STextJavaValidatorTest() {
-	}
-
-	@Before
-	public void setup() {
-		factory = SGraphFactory.eINSTANCE;
+public class STextJavaValidatorTest extends AbstractSTextValidationTest implements STextValidationMessages {
 
-		resource = new StextResource(URI.createURI(""));
-		injector.injectMembers(resource);
-		statechart = factory.createStatechart();
-		resource.getContents().add(statechart);
-
-		diagnostics = new BasicDiagnostic();
-		tester = new ValidatorTester<STextJavaValidator>(validator, injector);
-	}
-
-	@After
-	public void teardown() {
-		tester = null;
-	}
 
 	/**
 	 * @see STextJavaValidator#checkVariableDefinition(org.yakindu.sct.model.stext.stext.VariableDefinition)
@@ -598,115 +559,6 @@ public class STextJavaValidatorTest extends AbstractSTextTest implements STextVa
 		assertWarning(diagnostics, INTERNAL_DECLARATION_UNUSED);
 	}
 	
-	/**
-	 * Show warning when transition has no guard
-	 */
-	@Test
-	public void transitionsWithNoTrigger() {
-
-		Region region = factory.createRegion();
-
-		// create vertices for main region
-		Entry entry = factory.createEntry();
-		State a = factory.createState();
-		a.setName("A");
-		State b = factory.createState();
-		b.setName("B");
-		State c = factory.createState();
-		c.setName("C");
-		State d = factory.createState();
-		c.setName("D");
-		Choice e = factory.createChoice();
-		State f = factory.createState();
-		f.setName("F");
-		Transition entryToA = createTransition(entry, a);
-		Transition aToB = createTransition(a, b);
-		Transition bToC = createTransition(b, c);
-		Transition cToD = createTransition(c, d);
-		Transition eToF = createTransition(e, f);
-
-		// create vertices for compositState
-		State bb = factory.createState();
-		bb.setName("BB");
-		Entry entryB = factory.createEntry();
-		Exit exitB = factory.createExit();
-
-		Region b_region = factory.createRegion();
-		b_region.getVertices().add(entryB);
-		b_region.getVertices().add(bb);
-		b_region.getVertices().add(exitB);
-		b.getRegions().add(b_region);
-		Transition entryBToBB = createTransition(entryB, bb);
-		Transition bbToExitB = createTransition(bb, exitB);
-
-		region.getVertices().add(entry);
-		region.getVertices().add(a);
-		region.getVertices().add(b);
-		region.getVertices().add(c);
-		region.getVertices().add(d);
-		statechart.getRegions().add(region);
-
-		// transitions from entry point to State A -> valid model with no
-		// warnings
-		assertTrue(validator.validate(eToF, diagnostics, new HashMap<Object, Object>()));
-		assertIssueCount(diagnostics, 0);
-
-		// transitions from entry point to State A -> valid model with no
-		// warnings
-		assertTrue(validator.validate(entryToA, diagnostics, new HashMap<Object, Object>()));
-		assertIssueCount(diagnostics, 0);
-
-		// transition from StateA to StateB -> valid model with warnings expect
-		// 1 warning in total
-		assertTrue(validator.validate(aToB, diagnostics, new HashMap<Object, Object>()));
-		assertIssueCount(diagnostics, 1);
-		resetDiagnostics();
-
-		// transition from EntryB to StateBB -> valid model with no warnings
-		// expect 1 warning in total
-		assertTrue(validator.validate(entryBToBB, diagnostics, new HashMap<Object, Object>()));
-		assertIssueCount(diagnostics, 0);
-
-		// transition from BB to ExitB -> valid model with warnings expect 2
-		// warning in total
-		assertTrue(validator.validate(bbToExitB, diagnostics, new HashMap<Object, Object>()));
-		assertIssueCount(diagnostics, 1);
-		resetDiagnostics();
-
-		// transition from B to C -> valid model with no warning warnings expect
-		// 2 warning in total
-		assertTrue(validator.validate(bToC, diagnostics, new HashMap<Object, Object>()));
-		assertIssueCount(diagnostics, 0);
-
-		// transition from C to D -> valid model with warning warning expect 3
-		// warning in total
-		assertTrue(validator.validate(cToD, diagnostics, new HashMap<Object, Object>()));
-		assertIssueCount(diagnostics, 1);
-		resetDiagnostics();
-
-	}
-
-	/**
-	 * The outgoing transitions of a sync (fork / join) node must not have any
-	 * trigger part. Thus empty transitions must not have any warning. This test
-	 * case addresses a bug #75 (
-	 * https://code.google.com/a/eclipselabs.org/p/yakindu/issues/detail?id=75 )
-	 * .
-	 */
-	@Test
-	public void validEmptyTransitionFromSync() {
-		statechart = AbstractTestModelsUtil.loadStatechart(VALIDATION_TESTMODEL_DIR
-				+ "ValidEmptyTransitionFromSync.sct");
-		Iterator<EObject> iter = statechart.eAllContents();
-		while (iter.hasNext()) {
-			EObject element = iter.next();
-			if (element instanceof Transition) {
-				validator.validate(element, diagnostics, new HashMap<Object, Object>());
-			}
-		}
-
-		assertIssueCount(diagnostics, 0);
-	}
 
 	@Test
 	public void checkImportExists() {
@@ -716,42 +568,11 @@ public class STextJavaValidatorTest extends AbstractSTextTest implements STextVa
 		AssertableDiagnostics validationResult = tester.validate(importScope.getImports().get(0));
 		validationResult.assertError(STextJavaValidator.IMPORT_NOT_RESOLVED);
 	}
-
-	protected Transition createTransition(Vertex source, Vertex target) {
-		Transition trans = SGraphFactory.eINSTANCE.createTransition();
-		trans.setSource(source);
-		trans.setTarget(target);
-		source.getOutgoingTransitions().add(trans);
-		target.getIncomingTransitions().add(trans);
-		return trans;
-	}
-
-	protected void assertError(Diagnostic diag, String message) {
-		Diagnostic d = issueByName(diag, message);
-		assertNotNull("Issue '" + message + "' does not exist.", issueByName(diag, message));
-		assertEquals("Issue '" + message + "' is no error.", Diagnostic.ERROR, d.getSeverity());
-	}
-
-	protected void assertWarning(Diagnostic diag, String message) {
-		Diagnostic d = issueByName(diag, message);
-		assertNotNull("Issue '" + message + "' does not exist.", issueByName(diag, message));
-		assertEquals("Issue '" + message + "' is no warning.", Diagnostic.WARNING, d.getSeverity());
-	}
-
-	protected void assertIssueCount(Diagnostic diag, int count) {
-		int c = diag.getChildren().size();
-		assertEquals("expected " + count + " issue(s) but were " + c + " [" + diag.toString() + "]", count, c);
-	}
-
-	protected Diagnostic issueByName(Diagnostic diag, String message) {
-		for (Diagnostic issue : diag.getChildren()) {
-			if (message.equals(issue.getMessage()))
-				return issue;
-		}
-		return null;
-	}
-
-	protected void resetDiagnostics() {
-		diagnostics = new BasicDiagnostic();
+	
+	/**
+	 * The erelevant testst are implemented by TransitionsWithNoTriggerTest.
+	 */
+	@Test public void transitionsWithNoTrigger() {
 	}
+	
 }

+ 224 - 0
test-plugins/org.yakindu.sct.model.stext.test/src/org/yakindu/sct/model/stext/test/validation/TransitionsWithNoTriggerTest.java

@@ -0,0 +1,224 @@
+/**
+ * Copyright (c) 2015 itemis AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ * 	itemis AG - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.model.stext.test.validation;
+
+import static org.eclipse.xtext.EcoreUtil2.eAllOfType;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.yakindu.sct.model.sgraph.util.SGgraphUtil.firstNamed;
+
+import java.util.HashMap;
+
+import org.eclipse.xtext.junit4.InjectWith;
+import org.eclipse.xtext.junit4.XtextRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.yakindu.sct.model.sgraph.Choice;
+import org.yakindu.sct.model.sgraph.Entry;
+import org.yakindu.sct.model.sgraph.Exit;
+import org.yakindu.sct.model.sgraph.Region;
+import org.yakindu.sct.model.sgraph.State;
+import org.yakindu.sct.model.sgraph.Synchronization;
+import org.yakindu.sct.model.sgraph.Transition;
+import org.yakindu.sct.model.stext.stext.ReactionTrigger;
+import org.yakindu.sct.model.stext.stext.StextFactory;
+import org.yakindu.sct.model.stext.test.util.STextInjectorProvider;
+import org.yakindu.sct.model.stext.validation.STextValidationMessages;
+
+/** 
+ * @author terfloth - Initial contribution
+ * 
+ */
+@RunWith(XtextRunner.class)
+@InjectWith(STextInjectorProvider.class)
+public class TransitionsWithNoTriggerTest extends AbstractSTextValidationTest implements STextValidationMessages {
+	
+	
+	
+	private Entry entry;
+	protected State stateA;
+	private State stateB;
+	private State stateC;
+	private State stateD;
+	private Choice choice;
+	private State stateE;
+	private Transition entryToStateA;
+	private Transition stateAToStateB;
+	private Transition stateBToStateC;
+	private Transition stateCToStateD;
+	private Transition choiceToStateE;
+	private State stateBB;
+	private Entry entryB;
+	private Exit exitB;
+	private Region regionB;
+	private Transition entryBToStateBB;
+	private Transition stateBBToExitB;
+
+	
+	@Override @Before 
+	public void setup() {
+		super.setup();
+		
+		StextFactory stextFactory = StextFactory.eINSTANCE;
+		
+		Region region = factory.createRegion();
+
+		entry = factory.createEntry();
+		stateA = factory.createState();
+		stateA.setName("A");
+		stateB = factory.createState();
+		stateB.setName("B");
+		stateC = factory.createState();
+		stateC.setName("C");
+		stateD = factory.createState();
+		stateD.setName("D");
+		choice = factory.createChoice();
+		stateE = factory.createState();
+		stateE.setName("E");
+		entryToStateA = createTransition(entry, stateA);
+		stateAToStateB = createTransition(stateA, stateB);
+		stateBToStateC = createTransition(stateB, stateC);
+
+		stateCToStateD = createTransition(stateC, stateD);
+		stateCToStateD.setSpecification("always");
+		ReactionTrigger triggerCToD = stextFactory.createReactionTrigger();
+		triggerCToD.getTriggers().add(stextFactory.createAlwaysEvent());
+		stateCToStateD.setTrigger(triggerCToD);
+		
+		choiceToStateE = createTransition(choice, stateE);
+
+		stateBB = factory.createState();
+		stateBB.setName("BB");
+		entryB = factory.createEntry();
+		exitB = factory.createExit();
+
+		regionB = factory.createRegion();
+		regionB.getVertices().add(entryB);
+		regionB.getVertices().add(stateBB);
+		regionB.getVertices().add(exitB);
+		stateB.getRegions().add(regionB);
+		entryBToStateBB = createTransition(entryB, stateBB);
+		stateBBToExitB = createTransition(stateBB, exitB);
+
+		region.getVertices().add(entry);
+		region.getVertices().add(stateA);
+		region.getVertices().add(stateB);
+		region.getVertices().add(stateC);
+		region.getVertices().add(stateD);
+		statechart.getRegions().add(region);	
+	}
+
+	
+	
+	/** A transition from an entry to a state must have no trigger. */
+	@Test public void noTriggerOnTopLevelEntryToState() {
+
+		assertTrue(validator.validate(entryToStateA, diagnostics, new HashMap<Object, Object>()));
+		assertIssueCount(diagnostics, 0);
+	}
+
+	/** A transition from an entry to a state must have no trigger. */
+	@Test public void noTriggerOnSubStateEntryToState() {
+
+		assertTrue(validator.validate(entryBToStateBB, diagnostics, new HashMap<Object, Object>()));
+		assertIssueCount(diagnostics, 0);
+	}
+
+	/** No trigger on a transition from a choice to a state is valid. */
+	@Test public void noTriggerOnChoiceToState() {
+
+		assertTrue(validator.validate(choiceToStateE, diagnostics, new HashMap<Object, Object>()));
+		assertIssueCount(diagnostics, 0);
+	}
+
+	/** A transition from a state with exit may have no trigger. */
+	@Test public void noTriggerOnExitTransition() {
+
+		assertTrue(validator.validate(stateBToStateC, diagnostics, new HashMap<Object, Object>()));
+		assertIssueCount(diagnostics, 0);
+	}
+
+	/** A transition between two regular states (with no exit) should have a trigger. */
+	@Test public void missingTriggerOnStateToState() {
+
+		assertTrue(validator.validate(stateAToStateB, diagnostics, new HashMap<Object, Object>()));
+		assertIssueCount(diagnostics, 1);
+	}
+
+	/** A transition from a state to an exit should have a trigger. */
+	@Test public void missingTriggerOnStateToExit() {
+
+		assertTrue(validator.validate(stateBBToExitB, diagnostics, new HashMap<Object, Object>()));
+		assertIssueCount(diagnostics, 1);
+	}
+
+	/** A transition from a state to a state with a trigger must issue no warning. */
+	@Test public void existingTriggerOnStateToState() {
+
+		assertTrue(validator.validate(stateCToStateD, diagnostics, new HashMap<Object, Object>()));
+		assertIssueCount(diagnostics, 0);
+	}
+
+	
+	/**
+	 * The outgoing transitions of a sync (fork / join) node must not have any
+	 * trigger part. Thus empty transitions must not have any warning. This test
+	 * case addresses a bug #75 (
+	 * https://code.google.com/a/eclipselabs.org/p/yakindu/issues/detail?id=75 )
+	 * .
+	 */
+	@Test public void noTriggerOnSyncOutgoing() {
+		statechart = loadStatechart("ValidEmptyTransitionFromSync.sct");
+		
+		Region validRegion = firstNamed(eAllOfType(statechart, Region.class), "valid");
+		Synchronization sync = eAllOfType(validRegion, Synchronization.class).get(0);
+		
+		for (Transition t : sync.getOutgoingTransitions()) {
+			assertTrue(validate(t));
+			assertIssueCount(diagnostics, 0);
+		}
+	}
+
+	/**
+	 * If a sync node has multiple incoming transitions then the transitions can omit the trigger.
+	 */
+	@Test public void noTriggerOnSyncIncoming() {
+		statechart = loadStatechart("ValidEmptyTransitionFromSync.sct");
+		
+		Region validRegion = firstNamed(eAllOfType(statechart, Region.class), "valid");
+		Synchronization sync = eAllOfType(validRegion, Synchronization.class).get(0);
+		
+		for (Transition t : sync.getIncomingTransitions()) {
+			assertTrue(validate(t));
+			assertIssueCount(diagnostics, 0);
+		}
+	}
+
+	
+	/**
+	 * If a sync node has multiple incoming transitions then the transitions can omit the trigger.
+	 */
+	@Test public void missingTriggerOnSyncSingleIncoming() {
+		statechart = loadStatechart("ValidEmptyTransitionFromSync.sct");
+		
+		Region validRegion = firstNamed(eAllOfType(statechart, Region.class), "warning");
+		Synchronization sync = eAllOfType(validRegion, Synchronization.class).get(0);
+		
+		assertEquals(1, sync.getIncomingTransitions().size());
+		assertTrue(validate(sync.getIncomingTransitions().get(0)));
+		assertIssueCount(diagnostics, 1);
+		assertWarning(diagnostics, ISSUE_TRANSITION_WITHOUT_TRIGGER);
+	}
+
+
+}

+ 176 - 3
test-plugins/org.yakindu.sct.test.models/testmodels/validation/ValidEmptyTransitionFromSync.sct

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:sgraph="http://www.yakindu.org/sct/sgraph/2.0.0">
   <sgraph:Statechart xmi:id="_x2hFAG_pEeS1xYwspMh3zQ" specification="interface:&#xA;&#xA;&#x9;in event e" name="ValidEmptyTransitionFromSync">
-    <regions xmi:id="_x2iTIm_pEeS1xYwspMh3zQ" name="main region">
+    <regions xmi:id="_x2iTIm_pEeS1xYwspMh3zQ" name="valid">
       <vertices xsi:type="sgraph:Entry" xmi:id="_x2nysW_pEeS1xYwspMh3zQ">
         <outgoingTransitions xmi:id="_x2pn4W_pEeS1xYwspMh3zQ" target="_x2oZxm_pEeS1xYwspMh3zQ"/>
       </vertices>
@@ -19,7 +19,7 @@
             <outgoingTransitions xmi:id="_CPRcIG_qEeS1xYwspMh3zQ" specification="" target="_9n_vAG_pEeS1xYwspMh3zQ"/>
           </vertices>
           <vertices xsi:type="sgraph:State" xmi:id="_9n_vAG_pEeS1xYwspMh3zQ" name="AB" incomingTransitions="_CPRcIG_qEeS1xYwspMh3zQ">
-            <outgoingTransitions xmi:id="_UnqIsG_qEeS1xYwspMh3zQ" specification="always" target="_E0H-gG_qEeS1xYwspMh3zQ"/>
+            <outgoingTransitions xmi:id="_UnqIsG_qEeS1xYwspMh3zQ" specification="" target="_E0H-gG_qEeS1xYwspMh3zQ"/>
           </vertices>
         </regions>
       </vertices>
@@ -37,6 +37,26 @@
         <outgoingTransitions xmi:id="_gUMy4G_rEeS1xYwspMh3zQ" specification="" target="_dNqfwG_rEeS1xYwspMh3zQ"/>
       </vertices>
     </regions>
+    <regions xmi:id="_QeSjYPsbEeWVQPyEgylH1g" name="warning">
+      <vertices xsi:type="sgraph:State" xmi:id="_YWyJoPsbEeWVQPyEgylH1g" name="B">
+        <regions xmi:id="_YWywtfsbEeWVQPyEgylH1g" name="r1">
+          <vertices xsi:type="sgraph:State" xmi:id="_YWywtvsbEeWVQPyEgylH1g" name="BA" incomingTransitions="_YW1M8fsbEeWVQPyEgylH1g"/>
+        </regions>
+        <regions xmi:id="_YWywuPsbEeWVQPyEgylH1g" name="r2">
+          <vertices xsi:type="sgraph:State" xmi:id="_YWywufsbEeWVQPyEgylH1g" name="BB" incomingTransitions="_YW1M8vsbEeWVQPyEgylH1g"/>
+        </regions>
+      </vertices>
+      <vertices xsi:type="sgraph:Synchronization" xmi:id="_YW1M8PsbEeWVQPyEgylH1g" incomingTransitions="_cYZk8PsbEeWVQPyEgylH1g">
+        <outgoingTransitions xmi:id="_YW1M8fsbEeWVQPyEgylH1g" specification="" target="_YWywtvsbEeWVQPyEgylH1g"/>
+        <outgoingTransitions xmi:id="_YW1M8vsbEeWVQPyEgylH1g" specification="" target="_YWywufsbEeWVQPyEgylH1g"/>
+      </vertices>
+      <vertices xsi:type="sgraph:State" xmi:id="_aVNlMPsbEeWVQPyEgylH1g" name="A" incomingTransitions="_bocusPsbEeWVQPyEgylH1g">
+        <outgoingTransitions xmi:id="_cYZk8PsbEeWVQPyEgylH1g" specification="" target="_YW1M8PsbEeWVQPyEgylH1g"/>
+      </vertices>
+      <vertices xsi:type="sgraph:Entry" xmi:id="_bF6pYPsbEeWVQPyEgylH1g">
+        <outgoingTransitions xmi:id="_bocusPsbEeWVQPyEgylH1g" specification="" target="_aVNlMPsbEeWVQPyEgylH1g"/>
+      </vertices>
+    </regions>
   </sgraph:Statechart>
   <notation:Diagram xmi:id="_x2iTIG_pEeS1xYwspMh3zQ" type="org.yakindu.sct.ui.editor.editor.StatechartDiagramEditor" element="_x2hFAG_pEeS1xYwspMh3zQ" measurementUnit="Pixel">
     <children xmi:id="_x2lWcG_pEeS1xYwspMh3zQ" type="Region" element="_x2iTIm_pEeS1xYwspMh3zQ">
@@ -139,7 +159,7 @@
                   <styles xsi:type="notation:ShapeStyle" xmi:id="_9oA9IW_pEeS1xYwspMh3zQ" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
                   <styles xsi:type="notation:FontStyle" xmi:id="_9oA9Im_pEeS1xYwspMh3zQ"/>
                   <styles xsi:type="notation:BooleanValueStyle" xmi:id="_9oA9K2_pEeS1xYwspMh3zQ" name="isHorizontal" booleanValue="true"/>
-                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_9oA9I2_pEeS1xYwspMh3zQ" x="62" y="19"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_9oA9I2_pEeS1xYwspMh3zQ" x="65" y="20"/>
                 </children>
                 <layoutConstraint xsi:type="notation:Bounds" xmi:id="_4vERN2_pEeS1xYwspMh3zQ"/>
               </children>
@@ -241,6 +261,120 @@
       </children>
       <layoutConstraint xsi:type="notation:Bounds" xmi:id="_x2q2B2_pEeS1xYwspMh3zQ" x="10" y="10" width="200" height="400"/>
     </children>
+    <children xmi:id="_QeW00PsbEeWVQPyEgylH1g" type="Region" element="_QeSjYPsbEeWVQPyEgylH1g">
+      <children xsi:type="notation:DecorationNode" xmi:id="_QedigPsbEeWVQPyEgylH1g" type="RegionName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_QedigfsbEeWVQPyEgylH1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_QedigvsbEeWVQPyEgylH1g"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_QeeJkPsbEeWVQPyEgylH1g" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+        <children xmi:id="_YWwUcPsbEeWVQPyEgylH1g" type="State" element="_YWyJoPsbEeWVQPyEgylH1g">
+          <children xsi:type="notation:DecorationNode" xmi:id="_YWwUcfsbEeWVQPyEgylH1g" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUcvsbEeWVQPyEgylH1g"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_YWwUc_sbEeWVQPyEgylH1g"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_YWwUdPsbEeWVQPyEgylH1g" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_YWwUdfsbEeWVQPyEgylH1g" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUdvsbEeWVQPyEgylH1g"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_YWwUd_sbEeWVQPyEgylH1g" type="StateFigureCompartment">
+            <children xmi:id="_YWwUePsbEeWVQPyEgylH1g" type="Region" element="_YWywtfsbEeWVQPyEgylH1g">
+              <children xsi:type="notation:DecorationNode" xmi:id="_YWwUefsbEeWVQPyEgylH1g" type="RegionName">
+                <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUevsbEeWVQPyEgylH1g"/>
+                <layoutConstraint xsi:type="notation:Location" xmi:id="_YWwUe_sbEeWVQPyEgylH1g"/>
+              </children>
+              <children xsi:type="notation:Shape" xmi:id="_YWwUfPsbEeWVQPyEgylH1g" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+                <children xmi:id="_YWwUffsbEeWVQPyEgylH1g" type="State" element="_YWywtvsbEeWVQPyEgylH1g">
+                  <children xsi:type="notation:DecorationNode" xmi:id="_YWwUfvsbEeWVQPyEgylH1g" type="StateName">
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUf_sbEeWVQPyEgylH1g"/>
+                    <layoutConstraint xsi:type="notation:Location" xmi:id="_YWwUgPsbEeWVQPyEgylH1g"/>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_YWwUgfsbEeWVQPyEgylH1g" type="StateTextCompartment">
+                    <children xsi:type="notation:Shape" xmi:id="_YWwUgvsbEeWVQPyEgylH1g" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+                      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUg_sbEeWVQPyEgylH1g"/>
+                    </children>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_YWwUhPsbEeWVQPyEgylH1g" type="StateFigureCompartment"/>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUhfsbEeWVQPyEgylH1g" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+                  <styles xsi:type="notation:FontStyle" xmi:id="_YWwUhvsbEeWVQPyEgylH1g"/>
+                  <styles xsi:type="notation:BooleanValueStyle" xmi:id="_YWwUh_sbEeWVQPyEgylH1g" name="isHorizontal" booleanValue="true"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUiPsbEeWVQPyEgylH1g" x="43" y="24"/>
+                </children>
+                <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUifsbEeWVQPyEgylH1g"/>
+              </children>
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUivsbEeWVQPyEgylH1g" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUi_sbEeWVQPyEgylH1g"/>
+            </children>
+            <children xmi:id="_YWwUjPsbEeWVQPyEgylH1g" type="Region" element="_YWywuPsbEeWVQPyEgylH1g">
+              <children xsi:type="notation:DecorationNode" xmi:id="_YWwUjfsbEeWVQPyEgylH1g" type="RegionName">
+                <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUjvsbEeWVQPyEgylH1g"/>
+                <layoutConstraint xsi:type="notation:Location" xmi:id="_YWwUj_sbEeWVQPyEgylH1g"/>
+              </children>
+              <children xsi:type="notation:Shape" xmi:id="_YWwUkPsbEeWVQPyEgylH1g" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+                <children xmi:id="_YWwUkfsbEeWVQPyEgylH1g" type="State" element="_YWywufsbEeWVQPyEgylH1g">
+                  <children xsi:type="notation:DecorationNode" xmi:id="_YWwUkvsbEeWVQPyEgylH1g" type="StateName">
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUk_sbEeWVQPyEgylH1g"/>
+                    <layoutConstraint xsi:type="notation:Location" xmi:id="_YWwUlPsbEeWVQPyEgylH1g"/>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_YWwUlfsbEeWVQPyEgylH1g" type="StateTextCompartment">
+                    <children xsi:type="notation:Shape" xmi:id="_YWwUlvsbEeWVQPyEgylH1g" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+                      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUl_sbEeWVQPyEgylH1g"/>
+                    </children>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_YWwUmPsbEeWVQPyEgylH1g" type="StateFigureCompartment"/>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUmfsbEeWVQPyEgylH1g" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+                  <styles xsi:type="notation:FontStyle" xmi:id="_YWwUmvsbEeWVQPyEgylH1g"/>
+                  <styles xsi:type="notation:BooleanValueStyle" xmi:id="_YWwUm_sbEeWVQPyEgylH1g" name="isHorizontal" booleanValue="true"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUnPsbEeWVQPyEgylH1g" x="48" y="22"/>
+                </children>
+                <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUnfsbEeWVQPyEgylH1g"/>
+              </children>
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUnvsbEeWVQPyEgylH1g" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUn_sbEeWVQPyEgylH1g"/>
+            </children>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_YWwUoPsbEeWVQPyEgylH1g" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_YWwUofsbEeWVQPyEgylH1g"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_YWwUovsbEeWVQPyEgylH1g" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWwUo_sbEeWVQPyEgylH1g" x="43" y="409" width="345" height="160"/>
+        </children>
+        <children xsi:type="notation:Shape" xmi:id="_YWxikPsbEeWVQPyEgylH1g" type="Synchronization" element="_YW1M8PsbEeWVQPyEgylH1g" fontName="Verdana" lineColor="4210752">
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_YWxikfsbEeWVQPyEgylH1g" x="170" y="329" width="80" height="8"/>
+        </children>
+        <children xmi:id="_aVOMQPsbEeWVQPyEgylH1g" type="State" element="_aVNlMPsbEeWVQPyEgylH1g">
+          <children xsi:type="notation:DecorationNode" xmi:id="_aVOzUPsbEeWVQPyEgylH1g" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_aVOzUfsbEeWVQPyEgylH1g"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_aVOzUvsbEeWVQPyEgylH1g"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_aVOzU_sbEeWVQPyEgylH1g" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_aVOzVPsbEeWVQPyEgylH1g" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_aVOzVfsbEeWVQPyEgylH1g"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_aVPaYPsbEeWVQPyEgylH1g" type="StateFigureCompartment"/>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_aVOMQfsbEeWVQPyEgylH1g" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_aVOMQvsbEeWVQPyEgylH1g"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_aVPaYfsbEeWVQPyEgylH1g" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_aVOMQ_sbEeWVQPyEgylH1g" x="195" y="132"/>
+        </children>
+        <children xmi:id="_bF8ekPsbEeWVQPyEgylH1g" type="Entry" element="_bF6pYPsbEeWVQPyEgylH1g">
+          <children xmi:id="_bF9FoPsbEeWVQPyEgylH1g" type="BorderItemLabelContainer">
+            <children xsi:type="notation:DecorationNode" xmi:id="_bF9Fo_sbEeWVQPyEgylH1g" type="BorderItemLabel">
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_bF9FpPsbEeWVQPyEgylH1g"/>
+              <layoutConstraint xsi:type="notation:Location" xmi:id="_bF9FpfsbEeWVQPyEgylH1g"/>
+            </children>
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_bF9FofsbEeWVQPyEgylH1g" fontName="Verdana" lineColor="4210752"/>
+            <layoutConstraint xsi:type="notation:Bounds" xmi:id="_bF9FovsbEeWVQPyEgylH1g"/>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_bF8ekfsbEeWVQPyEgylH1g" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+          <styles xsi:type="notation:NamedStyle" xmi:id="_bF8ekvsbEeWVQPyEgylH1g" name="allowColors"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_bF8ek_sbEeWVQPyEgylH1g" x="114" y="41"/>
+        </children>
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_QeeJkfsbEeWVQPyEgylH1g"/>
+      </children>
+      <styles xsi:type="notation:ShapeStyle" xmi:id="_QeW00fsbEeWVQPyEgylH1g" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_QeW00vsbEeWVQPyEgylH1g" x="676" y="10" width="456" height="623"/>
+    </children>
     <styles xsi:type="notation:DiagramStyle" xmi:id="_x2iTIW_pEeS1xYwspMh3zQ"/>
     <edges xmi:id="_x2qO8G_pEeS1xYwspMh3zQ" type="Transition" element="_x2pn4W_pEeS1xYwspMh3zQ" source="_x2nysm_pEeS1xYwspMh3zQ" target="_x2oZyW_pEeS1xYwspMh3zQ">
       <children xsi:type="notation:DecorationNode" xmi:id="_x2qO9G_pEeS1xYwspMh3zQ" type="TransitionExpression">
@@ -320,5 +454,44 @@
       <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_jIHE8G_rEeS1xYwspMh3zQ" id="(0.08259587020648967,0.025)"/>
       <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_jIHE8W_rEeS1xYwspMh3zQ" id="(0.10541310541310542,0.014634146341463415)"/>
     </edges>
+    <edges xmi:id="_YW10APsbEeWVQPyEgylH1g" type="Transition" element="_YW1M8fsbEeWVQPyEgylH1g" source="_YWxikPsbEeWVQPyEgylH1g" target="_YWwUffsbEeWVQPyEgylH1g">
+      <children xsi:type="notation:DecorationNode" xmi:id="_YW10AfsbEeWVQPyEgylH1g" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_YW10AvsbEeWVQPyEgylH1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_YW10A_sbEeWVQPyEgylH1g" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_YW10BPsbEeWVQPyEgylH1g" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_YW10BfsbEeWVQPyEgylH1g" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_YW10BvsbEeWVQPyEgylH1g" points="[-2, 3, 71, -178]$[-66, 205, 7, 24]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_YW10B_sbEeWVQPyEgylH1g" id="(0.225,0.625)"/>
+    </edges>
+    <edges xmi:id="_YW10CPsbEeWVQPyEgylH1g" type="Transition" element="_YW1M8vsbEeWVQPyEgylH1g" source="_YWxikPsbEeWVQPyEgylH1g" target="_YWwUkfsbEeWVQPyEgylH1g">
+      <children xsi:type="notation:DecorationNode" xmi:id="_YW10CfsbEeWVQPyEgylH1g" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_YW10CvsbEeWVQPyEgylH1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_YW10C_sbEeWVQPyEgylH1g" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_YW10DPsbEeWVQPyEgylH1g" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_YW10DfsbEeWVQPyEgylH1g" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_YW10DvsbEeWVQPyEgylH1g" points="[1, 4, -67, -176]$[68, 204, 0, 24]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_YW10D_sbEeWVQPyEgylH1g" id="(0.8125,0.75)"/>
+    </edges>
+    <edges xmi:id="_boej4PsbEeWVQPyEgylH1g" type="Transition" element="_bocusPsbEeWVQPyEgylH1g" source="_bF8ekPsbEeWVQPyEgylH1g" target="_aVOMQPsbEeWVQPyEgylH1g">
+      <children xsi:type="notation:DecorationNode" xmi:id="_bofK8PsbEeWVQPyEgylH1g" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_bofK8fsbEeWVQPyEgylH1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_bofK8vsbEeWVQPyEgylH1g" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_boej4fsbEeWVQPyEgylH1g" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_boej4_sbEeWVQPyEgylH1g" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_boej4vsbEeWVQPyEgylH1g" points="[5, 5, -86, -103]$[97, 84, 6, -24]"/>
+    </edges>
+    <edges xmi:id="_cYazEPsbEeWVQPyEgylH1g" type="Transition" element="_cYZk8PsbEeWVQPyEgylH1g" source="_aVOMQPsbEeWVQPyEgylH1g" target="_YWxikPsbEeWVQPyEgylH1g">
+      <children xsi:type="notation:DecorationNode" xmi:id="_cYazFPsbEeWVQPyEgylH1g" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_cYazFfsbEeWVQPyEgylH1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_cYazFvsbEeWVQPyEgylH1g" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_cYazEfsbEeWVQPyEgylH1g" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_cYazE_sbEeWVQPyEgylH1g" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_cYazEvsbEeWVQPyEgylH1g" points="[2, 20, -6, -153]$[12, 177, 4, 4]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_cYcoQPsbEeWVQPyEgylH1g" id="(0.225,0.6037735849056604)"/>
+    </edges>
   </notation:Diagram>
 </xmi:XMI>