[genmodel.fsm] Fix wrong validation errors for cyclic transition chains
Bug 569188
Change-Id: I99bdd5a6f33fb5e4d6d5edd3712c6a0c6343d1b1
diff --git a/plugins/org.eclipse.etrice.core.genmodel.fsm/src/org/eclipse/etrice/core/genmodel/fsm/ExtendedFsmGenBuilder.xtend b/plugins/org.eclipse.etrice.core.genmodel.fsm/src/org/eclipse/etrice/core/genmodel/fsm/ExtendedFsmGenBuilder.xtend
index cc7ba54..cf484dd 100644
--- a/plugins/org.eclipse.etrice.core.genmodel.fsm/src/org/eclipse/etrice/core/genmodel/fsm/ExtendedFsmGenBuilder.xtend
+++ b/plugins/org.eclipse.etrice.core.genmodel.fsm/src/org/eclipse/etrice/core/genmodel/fsm/ExtendedFsmGenBuilder.xtend
@@ -14,8 +14,11 @@
package org.eclipse.etrice.core.genmodel.fsm
+import java.util.ArrayDeque
+import java.util.Deque
import java.util.HashMap
import java.util.List
+import java.util.Set
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EStructuralFeature
import org.eclipse.etrice.core.fsm.fSM.FSMPackage
@@ -75,7 +78,7 @@
def withChainHeads(GraphContainer gc) {
if (!gc.initializedChainHeads) {
if (gc.graph!==null) {
- gc.graph.allChainHeads.forEach[it.followChain(it)]
+ gc.graph.allChainHeads.forEach[it.followChain(it, newHashSet, new ArrayDeque)]
}
gc.initializedChainHeads = true
}
@@ -101,7 +104,7 @@
return gc
}
- private def void followChain(Link l, Link head) {
+ private def void followChain(Link l, Link head, Set<Node> visited, Deque<Node> stack) {
// if we started at an initial or guarded transition no interface item can be provided
if (!(head.transition instanceof TriggeredTransition)) {
l.ifitemTriggered = false
@@ -115,18 +118,21 @@
if (target instanceof State || target instanceof TransitionPoint) {
return
}
- else {
- // check whether we already visited the target node
- if(!l.target.outgoing.empty && l.target.outgoing.head.chainHeads.contains(head)) {
- // the transition chain generator can't handle cyclic transition chains
- validationError("This transition is part of a cyclic transition chain", l.transition, null);
- return;
- }
-
+ // check whether we already came from the target of this link
+ else if(stack.contains(l.target)) {
+ // the transition chain generator can't handle cyclic transition chains
+ validationError("This transition is part of a cyclic transition chain", l.transition, null);
+ return;
+ }
+ // only proceed if we did not visit the target of this link already
+ else if(!visited.contains(l.target)) {
+ visited.add(l.target);
+ stack.addLast(l.target);
// follow all outgoing links recursively
for (next : l.target.outgoing) {
- next.followChain(head)
+ next.followChain(head, visited, stack)
}
+ stack.removeLast();
}
}