Browse Source

Merge pull request #949 from Yakindu/issue_194_namingService

TreeNamingService
Rene Beckmann 8 years ago
parent
commit
33327c593a

+ 86 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/naming/ElementNameProvider.xtend

@@ -0,0 +1,86 @@
+/**
+ *   Copyright (c) 2016 committers of YAKINDU Statechart Tools.
+ *   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:
+ * 		@author René Beckmann (beckmann@itemis.de)
+ */
+
+package org.yakindu.sct.model.sexec.naming
+
+import javax.inject.Inject
+import org.eclipse.emf.ecore.EObject
+import org.yakindu.base.base.NamedElement
+import org.yakindu.sct.model.sexec.ExecutionFlow
+import org.yakindu.sct.model.sexec.ExecutionNode
+import org.yakindu.sct.model.sexec.ExecutionScope
+import org.yakindu.sct.model.sexec.ExecutionState
+import org.yakindu.sct.model.sexec.Step
+import org.yakindu.sct.model.sgraph.Region
+import org.yakindu.sct.model.sgraph.Vertex
+import org.yakindu.sct.model.stext.naming.StextNameProvider
+import org.eclipse.xtext.naming.QualifiedName
+import org.yakindu.sct.model.sexec.Reaction
+import java.util.List
+import java.util.ArrayList
+
+class ElementNameProvider {
+	@Inject private StextNameProvider provider
+
+	def protected List<String> elementNameSegments(NamedElement e) {
+		val name = elementName(e);
+		var ArrayList<String> l;
+		if (name != null) {
+			l = new ArrayList<String>(name.getSegments());
+		} else {
+			l = new ArrayList<String>();
+		}
+
+		return l;
+	}
+
+	def protected dispatch QualifiedName elementName(ExecutionFlow it) {
+		return null;
+	}
+
+	def protected dispatch QualifiedName elementName(ExecutionScope it) {
+		return sourceElement.elementName()
+	}
+
+	def protected dispatch QualifiedName elementName(ExecutionState it) {
+		return sourceElement.elementName()
+	}
+
+	def protected dispatch QualifiedName elementName(EObject it) {
+		eContainer?.elementName()
+	}
+
+	def protected dispatch QualifiedName elementName(ExecutionNode it) {
+		return provider.getFullyQualifiedName(it).skipFirst(2)
+	}
+
+	// TODO: we should merge the region/vertex case into this base implementation; we should check whether it is used in any case at all (otherwise it could be replaced with the body of vertexOrRegionName)
+	def protected dispatch QualifiedName elementName(NamedElement it) {
+		return provider.getFullyQualifiedName(it).skipFirst(2)
+	}
+
+	def protected dispatch QualifiedName elementName(Reaction it) {
+		return provider.getFullyQualifiedName(it).skipFirst(2)
+	}
+
+	def protected dispatch QualifiedName elementName(Region it) {
+		return provider.getFullyQualifiedName(it).skipFirst(1)
+	}
+
+	def protected dispatch QualifiedName elementName(Step it) {
+		return eContainer.elementName()
+	}
+
+	def protected dispatch QualifiedName elementName(Vertex it) {
+		return provider.getFullyQualifiedName(it).skipFirst(1)
+	}
+
+}

+ 183 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/naming/ShortString.xtend

@@ -0,0 +1,183 @@
+/**
+ *   Copyright (c) 2016 committers of YAKINDU Statechart Tools.
+ *   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:
+ * 		@author René Beckmann (beckmann@itemis.de)
+ */
+
+package org.yakindu.sct.model.sexec.naming
+
+import java.lang.String
+
+class ShortString {
+	/*
+	 * Class that manages a string and shortened versions of it.
+	 */
+	private String originalString;
+
+	private int[] cutArray; // holds information if char is cut or not
+	private int[] previous_cutArray; // holds previous state for rollback / undo possibility
+	// cost of cutting operations
+	final static public int COST_LOWERCASE_VOCALS = 1;
+	final static public int COST_UNDERSCORE = 1;
+	final static public int COST_LOWERCASE_CONSONANTS = 2;
+	final static public int COST_UPPERCASE = 3;
+	final static public int COST_DIGIT = 10;
+	final static public int COST_FIRSTLETTER = 10;
+
+	new(String s) {
+		if (s == null) {
+			originalString = "";
+		} else {
+			originalString = s;
+		}
+		cutArray = newIntArrayOfSize(size);
+		previous_cutArray = newIntArrayOfSize(size);
+		reset();
+		saveCurrentToPrevious();
+	}
+
+	def public getOriginalString() {
+		originalString
+	}
+
+	def private int size() {
+		// instead of saving originalString.length as an own member
+		originalString.length
+	}
+
+	def public reset() {
+		// Reset cut_array so that the shortened String is equal to the original String.
+		saveCurrentToPrevious();
+		for (var i = 0; i < size; i++) {
+			cutArray.set(i, 1);
+		}
+	}
+
+	def private saveCurrentToPrevious() {
+		// save current cut-state to previous_cutArray.
+		for (var i = 0; i < size; i++) {
+			previous_cutArray.set(i, cutArray.get(i));
+		}
+	}
+
+	def public rollback() {
+		// return to previous state
+		for (var i = 0; i < size; i++) {
+			cutArray.set(i, previous_cutArray.get(i));
+		}
+	}
+
+	def public String getShortenedString() {
+		// return the current version of the shortened string according to cutArray
+		var sb = new StringBuilder();
+
+		for (var i = 0; i < size; i++) {
+			if (cutArray.get(i) != 0) {
+				sb.append(originalString.charAt(i));
+			}
+		}
+
+		sb.toString;
+	}
+
+	def public int getShortenedSize() {
+		var length = 0;
+		for (var i = 0; i < size; i++) {
+			if (cutArray.get(i) != 0) {
+				length += 1;
+			}
+		}
+
+		return length;
+	}
+
+	def public int getCutCostFactor() {
+		// factor that takes into account how much of the string is already cut, so that cutting away more characters get's more expensive
+		return 10 + (getCutRatio() * 10) as int;
+	}
+
+	def public int getCutCost() {
+		// returns the current cutting cost of the ShortString by iterating over the cutArray and accumulating cost per index
+		if (1.0 - getCutRatio() < 0.001) {
+			return Integer.MAX_VALUE;
+		}
+		var cost = 0;
+
+		for (var i = 0; i < size; i++) {
+			if (cutArray.get(i) == 0) {
+				cost += getBaseCutCost(i);
+			}
+		}
+
+		return cost * getCutCostFactor;
+	}
+
+	def public int getBaseCutCost(int index) {
+		// returns the cut cost of this char, independent of its cut state.
+		var cost = 0;
+
+		var c = originalString.charAt(index);
+
+		if (index == 0) {
+			cost += org.yakindu.sct.model.sexec.naming.ShortString.COST_FIRSTLETTER;
+		}
+		if (Character.isDigit(c)) {
+			cost += org.yakindu.sct.model.sexec.naming.ShortString.COST_DIGIT;
+		} else if (Character.isUpperCase(c)) {
+			cost += org.yakindu.sct.model.sexec.naming.ShortString.COST_UPPERCASE;
+		} else if (isLowercaseVocal(c)) {
+			cost += org.yakindu.sct.model.sexec.naming.ShortString.COST_LOWERCASE_VOCALS;
+		} else if (c.toString().equals("_")) {
+			cost += org.yakindu.sct.model.sexec.naming.ShortString.COST_UNDERSCORE;
+		} else {
+			cost += org.yakindu.sct.model.sexec.naming.ShortString.COST_LOWERCASE_CONSONANTS;
+		}
+
+		return cost;
+	}
+
+	def public removeCheapestChar() {
+		// of all possible characters that aren't cut yet, remove the one with the lowest cutting cost.
+		// saveCurrentToPrevious(); - done in removeIndex(i);
+		var cheapestOperation_cost = Integer.MAX_VALUE;
+		var cheapestOperation_index = 0;
+		for (var i = 0; i < size; i++) {
+			if (cutArray.get(i) != 0) {
+				var cost = getBaseCutCost(i);
+				if (cost < cheapestOperation_cost) {
+					cheapestOperation_cost = cost;
+					cheapestOperation_index = i;
+				}
+			}
+		}
+
+		removeIndex(cheapestOperation_index);
+	}
+
+	def public float getCutRatio() {
+		// returns the ratio of characters that are cut.
+		1 - ((getShortenedSize as float) / (size as float))
+	}
+
+	def public removeIndex(int index) {
+		saveCurrentToPrevious();
+		if (index < size) {
+			cutArray.set(index, 0);
+		}
+	}
+
+	def private boolean isLowercaseVocal(int i) {
+		var c = originalString.charAt(i);
+		return isLowercaseVocal(c);
+	}
+
+	def private boolean isLowercaseVocal(char c) {
+		val s = c.toString();
+		return (s == "a" || s == "e" || s == "i" || s == "o" || s == "u");
+	}
+}

+ 453 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/naming/StringTreeNode.xtend

@@ -0,0 +1,453 @@
+/**
+ *   Copyright (c) 2016 committers of YAKINDU Statechart Tools.
+ *   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:
+ * 		@author René Beckmann (beckmann@itemis.de)
+ */
+
+package org.yakindu.sct.model.sexec.naming
+
+import java.util.ArrayList
+import java.util.List
+import java.util.Comparator
+
+class StringTreeNodeDepthComparator implements Comparator<StringTreeNode> {
+	override compare(StringTreeNode o1, StringTreeNode o2) {
+		return o1.getDepth() - o2.getDepth();
+	}
+}
+
+class StringTreeNode {
+	/*
+	 * implements a data tree to hold the various statechart elements' names
+	 */
+	private String data;
+	private ArrayList<StringTreeNode> children;
+	private StringTreeNode parent;
+
+	/*
+	 * Constructors
+	 */
+	new(String data) {
+		this.data = data;
+		this.parent = null;
+		this.children = new ArrayList();
+	}
+
+	new() {
+		this.data = null;
+		this.parent = null;
+		this.children = new ArrayList();
+	}
+
+	/*
+	 * getters & setters
+	 */
+	def public ArrayList<StringTreeNode> getChildren() {
+		/*
+		 * getter for this.children
+		 */
+		return children;
+	}
+
+	def public String getData() {
+		/*
+		 * getter for this.data
+		 */
+		return data;
+	}
+
+	/*
+	 * Tree construction functions
+	 */
+	def public void addChild(StringTreeNode node) {
+		/*
+		 * Function to add a child to this node.
+		 */
+		node.parent = this;
+		children.add(node);
+	}
+
+	def public StringTreeNode addString(String s) {
+		/*
+		 * Cut the string into an ArrayList containing the single chars in the string,
+		 * and call addStringList afterwards.
+		 */
+		var sList = new ArrayList<String>();
+
+		for (var i = 0; i < s.length(); i++) {
+			sList.add(Character.toString(s.charAt(i)));
+		}
+		return this.addStringList(sList);
+	}
+
+	def public StringTreeNode addStringList(List<String> sList) {
+		/*
+		 * Adds an array of strings.
+		 * If the first element is found within own children's data,
+		 * cut the first element and call that child with this function recursively.
+		 * Else, create new child with that element, and proceed the same.
+		 */
+		if (sList.size() == 0) {
+			for (child : children) {
+				if (child.isEnd()) {
+					return child; // only add one end per node - don't allow double strings
+				}
+			}
+			val newNode = new StringTreeNode("");
+			addChild(newNode); // mark End
+			return newNode;
+		}
+
+		var firstString = sList.get(0); // first element to search in own children. If not found, create new one.
+		var rest = sList.subList(1, sList.size()); // the rest of the array that the child's addStringList function is called with
+		var newChild = true;
+
+		for (child : children) // search for child that fits
+		{
+			if (child.getData().equals(firstString)) {
+				newChild = false;
+				return child.addStringList(rest);
+			}
+		}
+		if (newChild) {
+			var newNode = new StringTreeNode(firstString);
+			addChild(newNode);
+			return newNode.addStringList(rest);
+		}
+
+	}
+
+	/*
+	 * Tree reading functions
+	 */
+	def public List<StringTreeNode> getNodes() {
+		var List<StringTreeNode> nodelist = new ArrayList<StringTreeNode>();
+
+		nodelist.add(this);
+
+		for (child : children) {
+			nodelist.addAll(child.getNodes())
+		}
+
+		return nodelist;
+	}
+
+	def public int getWeight() {
+		var weight = 0;
+
+		for (c : children) {
+			weight += c.getWeight() + 1; // + 1: count children as well
+		}
+
+		return weight;
+	}
+
+	def public int getDepth() {
+		// Upwards recursion to get distance from root
+		if (parent == null) {
+			return 0;
+		} else {
+			return parent.getDepth() + 1;
+		}
+	}
+
+	def public ArrayList<String> getSiblings(String fullName) {
+
+		val nodeChain = getNodeChain(fullName)
+		val lastNode = (nodeChain).get(nodeChain.size() - 1);
+
+		val siblings = lastNode.getSiblings();
+
+		val siblingsContents = new ArrayList<String>();
+
+		for (node : siblings) {
+			siblingsContents.add(node.getData());
+		}
+		return siblingsContents
+	}
+
+	def public ArrayList<StringTreeNode> getSiblings() {
+		// returns a list of the parent's children without this - can be empty.
+		if (isRoot()) {
+			return new ArrayList<StringTreeNode>();
+		} else {
+			var list = new ArrayList<StringTreeNode>(this.parent.getChildren()); // copy
+			list.removeAll(this);
+			return list;
+		}
+
+	}
+
+	def public ArrayList<String> getContents() {
+		/*
+		 * Returns a list of all strings contained in the tree
+		 */
+		var contents = new ArrayList<String>();
+		var endNodes = getEndNodes();
+
+		for (end : endNodes) {
+			contents.add(end.getContentUpwards());
+		}
+
+		return contents;
+	}
+
+	def public ArrayList<StringTreeNode> getEndNodes() {
+		/*
+		 * returns a list of nodes that are string ending nodes (node.isEnd() == true)
+		 */
+		var endNodes = new ArrayList<StringTreeNode>();
+
+		for (child : children) {
+			if (child.isEnd()) {
+				endNodes.add(child);
+			}
+			endNodes.addAll(child.getEndNodes());
+		}
+		return endNodes;
+	}
+
+	def public String getContentUpwards() {
+		/*
+		 * Traverse tree upwards and return the string ended by this node up to root
+		 */
+		var s = "";
+
+		if (!isRoot()) {
+			s = this.parent.getContentUpwards() + this.data;
+		}
+
+		return s;
+	}
+
+	def public String getShortName(String longname, int maxLen) {
+		var nodeChain = getNodeChain(longname);
+
+		var ret = "";
+
+		for (node : nodeChain) {
+			ret += node.getData();
+		}
+
+		return ret;
+	}
+
+	def public void delete() {
+		/*
+		 * All nodes have a reference to their parent (except the root node, where it's null) and their children.
+		 * Thus, when we want to delete a node, we need to cut it from its parent's children and
+		 * delete the reference to the parent. The rest of the tree is then 'floating' and will be garbage collected.
+		 */
+		if (!isRoot()) {
+			this.parent.deleteChild(this);
+			this.parent = null;
+		}
+	}
+
+	def public deleteChild(StringTreeNode child) {
+		this.children.removeAll(child);
+	}
+
+	def public ArrayList<StringTreeNode> getNodeChain(String name) {
+		/*
+		 * produces an ArrayList containing the Nodes that form the given string.
+		 */
+		var nodeChain = new ArrayList<StringTreeNode>();
+
+		if (children.size() == 0 || (children.size() == 1 && children.get(0).isEnd())) {
+			return nodeChain;
+		}
+
+		var maxEquality = 0;
+		var StringTreeNode maxEqualNode = null;
+
+		for (child : children) // find maximum equality in tree to select the correct branch
+		{
+			var childS = child.getData();
+			if (name.startsWith(childS) && childS.length() > maxEquality) {
+				maxEquality = childS.length();
+				maxEqualNode = child;
+			}
+		}
+
+		if (maxEqualNode == null) {
+			return null;
+		}
+
+		var rest = name.substring(maxEquality);
+
+		nodeChain.add(maxEqualNode);
+
+		val childrenNodeChain = maxEqualNode.getNodeChain(rest);
+
+		if (childrenNodeChain == null) {
+			return null;
+		}
+
+		nodeChain.addAll(childrenNodeChain);
+
+		return nodeChain;
+	}
+
+	def public StringTreeNode navigate(String content) {
+		for (child : children) {
+			if (content.equals(child.getData())) {
+				return child;
+			}
+		}
+
+		return null;
+	}
+
+	def public StringTreeNode getParent() {
+		return parent;
+	}
+
+	def public List<String> getChildrenContents() {
+		var returnList = new ArrayList<String>();
+
+		for (child : children) {
+			returnList.add(child.getData());
+		}
+
+		return returnList;
+	}
+
+	/*
+	 * Tree manipulating functions
+	 */
+	def public void compress() {
+		/*
+		 * Compresses branches.
+		 * All nodes 'X' that have only one child 'A' append 'A's data to their own, delete  'A' and
+		 * make 'A's children their ('X's) own.
+		 * Only exception: endNodes, according to node.isEnd() == true, are not consumed.
+		 * 
+		 * Example:
+		 * A, B, C... denote states, - denotes an edge, # denotes an end node, O the root node
+		 * 
+		 * O-A-B-C-D-E-#
+		 *        \
+		 *         F-G-#
+		 * 
+		 * becomes
+		 * 
+		 * O-ABC-DE-#
+		 *      \
+		 *       FG-#
+		 */
+		if (!isRoot()) // don't do for root, no data should be saved in root
+		{
+			while (this.children.length() == 1 && !children.get(0).isEnd()) {
+				var myChild = children.get(0); // reference to only child
+				this.children.removeAll(myChild); // delete from list
+				this.data += myChild.getData(); // append myChilds data to own
+				for (child : myChild.getChildren()) // adopt myChilds children as own
+				{
+					this.addChild(child);
+				}
+			}
+		}
+
+		for (child : this.children) // recursion
+		{
+			child.compress();
+		}
+
+	}
+
+	/*
+	 * Helper functions
+	 */
+	def public boolean isAncestor(StringTreeNode descendantNode) {
+		/*
+		 * Traverses the tree upwards and checks if the node this function is called on is an ancestor of the given node.
+		 * 
+		 * Example:
+		 * 
+		 * O-A-B-C-D
+		 *      \
+		 *       E
+		 * 
+		 * When called on 'B', given 'D', this should return true, but not the other way round:
+		 * 'D' is not root, and 'D's parent is not 'B', so the function is called again with 'C'. 'B' is 'C's parent, returns true.
+		 * 
+		 * When called on 'E', given 'C', this should return false, and has the same behaviour when called on 'C' given 'E'.
+		 * 1st. call: 'C' is not root, and 'C's parent is not 'E', so the function is called again with 'B'.
+		 * 2nd. call: 'B' is not root, and 'B's parent is not 'E', so the function is called again with 'A'.
+		 * 3rd. call: 'A' is not root, and 'A's parent is not 'E', so the function is called again with 'O', the root node.
+		 * 4th. call: 'O' is the root node, false is returned. E is not an ancestor of C.
+		 * 
+		 * ATTENTION: This function does NOT return true if this is a root node. This would not test if descendantNode
+		 * belongs to this tree.
+		 * 
+		 */
+		if (descendantNode.isRoot()) // obviously, this node can't be the ancestor when descendantNode is root
+		{
+			return false;
+		} else if (descendantNode.parent == this) {
+			return true;
+		} else {
+			return this.isAncestor(descendantNode.parent)
+		}
+	}
+
+	def public int getDistance(StringTreeNode otherNode) {
+		if (this == otherNode) {
+			return 0;
+		} else if (this.isRoot()) {
+			return otherNode.getDepth();
+		} else if (otherNode.isRoot()) {
+			return this.getDepth();
+		} else if (this.isAncestor(otherNode)) {
+			return otherNode.getDepth() - this.getDepth();
+		} else if (otherNode.isAncestor(this)) {
+			return this.getDepth() - otherNode.getDepth();
+		} else {
+			val commonAncestor = this.getCommonAncestor(otherNode);
+			val distance = this.getDepth() + otherNode.getDepth() - 2 * commonAncestor.getDepth();
+			return distance;
+		}
+	}
+
+	def public StringTreeNode getCommonAncestor(StringTreeNode otherNode) {
+		if (this == otherNode) {
+			return this;
+		} else if (this.isAncestor(otherNode)) {
+			return this;
+		} else if (otherNode.isAncestor(this)) {
+			return otherNode;
+		} else {
+			// find node next to root, climb upwards until ancestor of other node is found
+			var StringTreeNode upperNode;
+			var StringTreeNode underNode;
+			val thisDepth = this.getDepth();
+			val otherDepth = otherNode.getDepth();
+			if (thisDepth > otherDepth) {
+				upperNode = otherNode;
+				underNode = this;
+			} else {
+				upperNode = this;
+				underNode = otherNode;
+			}
+			while (!upperNode.isAncestor(underNode)) {
+				upperNode = upperNode.parent;
+			}
+			return upperNode;
+		}
+	}
+
+	def public boolean isRoot() {
+		return this.parent == null;
+	}
+
+	def public boolean isEnd() {
+		var ret = (this.children.size() == 0 && this.data.equals(""));
+		return ret;
+	}
+}

+ 651 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/naming/TreeNamingService.xtend

@@ -0,0 +1,651 @@
+/**
+ *   Copyright (c) 2016 committers of YAKINDU Statechart Tools.
+ *   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:
+ * 		@author René Beckmann (beckmann@itemis.de)
+ */
+
+package org.yakindu.sct.model.sexec.naming
+
+import java.util.ArrayList
+import java.util.HashMap
+import java.util.List
+import java.util.Map
+import javax.inject.Inject
+import org.eclipse.xtext.naming.IQualifiedNameProvider
+import org.yakindu.base.base.NamedElement
+import org.yakindu.sct.model.sexec.ExecutionFlow
+import org.yakindu.sct.model.sexec.ExecutionScope
+import org.yakindu.sct.model.sexec.ExecutionState
+import org.yakindu.sct.model.sexec.Step
+import org.yakindu.sct.model.sexec.extensions.SExecExtensions
+import org.yakindu.sct.model.sexec.transformation.StatechartExtensions
+import org.yakindu.sct.model.sgraph.CompositeElement
+import org.yakindu.sct.model.sgraph.Region
+import org.yakindu.sct.model.sgraph.State
+import org.yakindu.sct.model.sgraph.Statechart
+import org.yakindu.sct.model.sgraph.Vertex
+import org.yakindu.sct.model.stext.stext.TimeEventSpec
+import com.google.common.collect.Maps
+
+/** New implementation of the naming service for various identifiers used in the generated code. 
+ * It is responsible for identifier construction depending on the thing to be named including different strategies 
+ * which also include name shortening.
+ */
+class TreeNamingService implements INamingService {
+
+	@Inject extension SExecExtensions
+	@Inject extension StatechartExtensions
+	@Inject extension IQualifiedNameProvider
+
+	@Inject extension ElementNameProvider
+
+	@Inject private StringTreeNodeDepthComparator stringTreeNodeDepthComparator
+
+	// from public class org.yakindu.sct.generator.c.features.CDefaultFeatureValueProvider extends		
+	private static final String VALID_IDENTIFIER_REGEX = "[_a-zA-Z][_a-zA-Z0-9]*";
+
+	var protected int maxLength = 0;
+
+	var protected char separator = '_';
+
+	/*
+	 * Holds the name of each element whose name was requested.
+	 */
+	var protected Map<NamedElement, String> map;
+
+	/*
+	 * Holds the end node in the tree for each NamedElement that was added.
+	 */
+	var protected Map<NamedElement, StringTreeNode> treeMap;
+
+	/*
+	 * For each node in the tree, there is a mapping to a short string managing the shortening of the name.
+	 */
+	var protected Map<StringTreeNode, ShortString> node_shortString_map;
+
+	/*
+	 * For each end node, individualMap holds a List of Nodes which make this name individual. (a subset of the tree basically)
+	 */
+	var protected Map<StringTreeNode, ArrayList<StringTreeNode>> individualMap;
+
+	var protected boolean shortNamesValid; // marker to remember if the names are currently correctly shortened
+	var protected StringTreeNode tree; // the tree which holds the added names
+	// if the naming service is initialized with a flow, activeStatechart is null, and vice versa.
+	var protected ExecutionFlow activeFlow;
+
+	var protected Statechart activeStatechart;
+
+	new(int maxLength, char separator) {
+		this.maxLength = maxLength
+		this.separator = separator
+	}
+
+	new() {
+		this.maxLength = 0
+		this.separator = '_'
+	}
+
+	override initializeNamingService(Statechart statechart) {
+		if (tree == null || activeStatechart != statechart) {
+			map = Maps.newHashMap
+			treeMap = Maps.newHashMap
+			shortNamesValid = false;
+
+			activeFlow = null;
+			activeStatechart = statechart;
+			createNameTree(statechart);
+
+			individualMap = constructIndividualNames();
+			node_shortString_map = createShortStringMapping();
+
+			shortenNames();
+		}
+	}
+
+	def private void createNameTree(Statechart statechart) {
+		tree = new StringTreeNode();
+
+		addShortVertexNames(statechart);
+	}
+
+	def protected void addShortVertexNames(CompositeElement element) {
+		for (region : element.regions) {
+			addElement(region, new ArrayList<String>(), new ArrayList<String>());
+			for (vertex : region.vertices) {
+				switch vertex {
+					State:
+						addElement(vertex, new ArrayList<String>(), new ArrayList<String>())
+					default:
+						addElement(vertex, new ArrayList<String>(), new ArrayList<String>())
+				}
+			}
+		}
+		for (region : element.regions) {
+			for (vertex : region.vertices) {
+				if (vertex instanceof CompositeElement) {
+					addShortVertexNames(vertex as CompositeElement)
+				}
+			}
+		}
+	}
+
+	override initializeNamingService(ExecutionFlow flow) {
+		if (tree == null || activeFlow != flow) {
+			map = Maps.newHashMap
+			treeMap = Maps.newHashMap
+			shortNamesValid = false;
+
+			activeFlow = flow;
+			activeStatechart = null;
+
+			createNameTree(flow);
+			individualMap = constructIndividualNames();
+			node_shortString_map = createShortStringMapping();
+
+			shortenNames();
+		}
+	}
+
+	def private void createNameTree(ExecutionFlow flow) {
+		// Initialize tree
+		tree = new StringTreeNode();
+
+		for (region : flow.regions) {
+			addElement(region, new ArrayList<String>(), new ArrayList<String>());
+			for (node : region.nodes) {
+				addElement(node, new ArrayList<String>(), new ArrayList<String>());
+			}
+		}
+
+		for (state : flow.states) {
+			addElement(state, state.prefix, state.suffix);
+		}
+		for (func : flow.allFunctions) {
+			addElement(func, func.prefix, func.suffix);
+		}
+
+		// Create short name for time events of statechart
+		if (flow.sourceElement instanceof Statechart) {
+			val statechart = flow.sourceElement as Statechart
+			addShortTimeEventName(flow, statechart)
+		}
+
+		// Create short name for time events of states
+		for (executionState : flow.states) {
+			if (executionState.sourceElement instanceof State) {
+				val state = executionState.sourceElement as State
+				addShortTimeEventName(executionState, state)
+			}
+		}
+	}
+
+	def public test_printTreeContents() {
+		for (s : tree.getContents()) {
+			System.out.println(s);
+		}
+
+		System.out.println();
+	}
+
+	def protected addShortTimeEventName(NamedElement executionFlowElement, NamedElement sgraphElement) {
+		var timeEventSpecs = sgraphElement.timeEventSpecs;
+		for (tes : timeEventSpecs) {
+			val timeEvent = executionFlowElement.flow.getTimeEvent(sgraphElement.fullyQualifiedName + "_time_event_" +
+				timeEventSpecs.indexOf(tes))
+			if (timeEvent != null) {
+				addElement(executionFlowElement, prefix(tes, sgraphElement), suffix(tes, sgraphElement));
+			}
+		}
+	}
+
+	def private void addElement(NamedElement elem, List<String> prefix, List<String> suffix) {
+		val name = new ArrayList<String>(elem.elementNameSegments());
+		val segments = new ArrayList<String>();
+		segments.addAll(prefix);
+		segments.addAll(name);
+		segments.addAll(suffix);
+		if (!segments.isEmpty()) {
+			val addedNode = tree.addStringList(segments);
+
+			treeMap.put(elem, addedNode); // remember for later access
+			shortNamesValid = false;
+		}
+	// System.out.println(name);
+	}
+
+	def protected asIndexPosition(ExecutionScope it) {
+		superScope.subScopes.indexOf(it).toString;
+	}
+
+	def protected dispatch asSGraphIndexPosition(Region it) {
+		composite.regions.toList.indexOf(it).toString
+	}
+
+	def protected dispatch asSGraphIndexPosition(State it) {
+		parentRegion.vertices.filter(typeof(State)).toList.indexOf(it).toString
+	}
+
+	def protected dispatch asSGraphIndexPosition(Vertex it) {
+		parentRegion.vertices.toList.indexOf(it).toString
+	}
+
+	override public setMaxLength(int length) {
+		maxLength = length
+	}
+
+	override public setSeparator(char sep) {
+		// Check if Prefix is ok		
+		var String sepString = sep + ""
+		if (!(sepString.matches(VALID_IDENTIFIER_REGEX))) {
+			throw new IllegalArgumentException
+		}
+		separator = sep
+	}
+
+	override public getMaxLength() {
+		return maxLength
+	}
+
+	override public getSeparator() {
+		return separator
+	}
+
+	override getShortName(NamedElement element) {
+		// check if element was named before
+		if (map.containsKey(element)) {
+			return map.get(element);
+		}
+		// if not, check if element is located in the tree
+		if (!treeMap.containsKey(element)) {
+			addElement(element, new ArrayList<String>(), new ArrayList<String>());
+		}
+		// check if names are shortened already
+		if (!shortNamesValid) {
+			shortenNames();
+		}
+
+		val name = getShortenedName(element);
+
+		map.put(element, name);
+		return name;
+	}
+
+	def private Map<StringTreeNode, ArrayList<StringTreeNode>> constructIndividualNames() {
+		/*
+		 * The map doublets is a three dimensional construct.
+		 * For each end-node-name in the tree, it holds a list of lists describing that name.
+		 * The outer list contains instances representing the same name, and the inner lists hold 
+		 * the current set of nodes that is needed to make the name individual.
+		 * 
+		 * Consider the following simple tree:
+		 * main_region-StateA
+		 * main_region-StateB
+		 * second_region-StateA
+		 * 
+		 * After the initial phase, the map then contains the following:
+		 * {"StateA": [[node(StateA)], [node(StateA)]], "StateB": [[node(StateB)]]}
+		 * 
+		 * The iteration consists of two phases then.
+		 * In Phase 1, all inner lists are extended with the first element's parent - as long as there is more than one list.
+		 * This leads to the following:
+		 * {"StateA": [[node(main_region), node(StateA)], [node(second_region), node(StateA)]], "StateB": [[node(StateB)]]}
+		 * in Phase 2, the map is then resorted with the new names:
+		 * {
+		 * 	"main_region_StateA": [[node(main_region), node(StateA)]],
+		 * 	"second_region_StateA": [[node(second_region), node(StateA)]],
+		 * 	"StateB": [[node(StateB)]] 
+		 * }
+		 * 
+		 * As we can see, all outer lists now have exactly length 1, which is the abortion criterion.
+		 * 
+		 * In the finalization phase, we check if there are any weird things happening like randomly created double names.
+		 * For example, someone could create a state named "region_StateA" and two other elements named "region" and "StateA" could
+		 * be clumped together to form an individual name.
+		 * 
+		 */
+		 
+		// get all end-nodes, that is "ends of strings" added to the tree.
+		val nodes = tree.getEndNodes().sortWith(stringTreeNodeDepthComparator);
+		var doublets = new HashMap<String, ArrayList<ArrayList<StringTreeNode>>>();
+		val mapping = new HashMap<StringTreeNode, ArrayList<StringTreeNode>>();
+
+		// Initialization
+		for (node : nodes) {
+			if (!doublets.containsKey(node.data)) {
+				doublets.put(node.data, new ArrayList<ArrayList<StringTreeNode>>());
+			}
+			val list = new ArrayList<StringTreeNode>();
+			// add new inner list that will hold the nodes going to the end node forming the individual name
+			doublets.get(node.data).add(list);
+			// map this list to the end node. We'll return this map later, but we need to fill the lists first
+			mapping.put(node, list);
+			list.add(node);
+		}
+
+		var abort = false;
+		// Iteration
+		while (!abort) {
+			// Phase 1
+			for (name : doublets.keySet) {
+				// check outer list. If it contains more than one list, there is more than one element with the same name.
+				if (doublets.get(name).length > 1) {
+					// if that is the case, add one parent node to all inner node lists.
+					for (nodelist : doublets.get(name)) {
+						nodelist.add(0, nodelist.get(0).parent);
+					}
+				}
+			}
+
+			// Phase 2
+			val newDoublets = new HashMap<String, ArrayList<ArrayList<StringTreeNode>>>();
+
+			for (name : doublets.keySet) // for all keys
+			{
+				for (nodelist : doublets.get(name)) // for inner lists in outer lists - returned by doublets.get(name)
+				{
+					// construct names formed by inner lists, now possibly extended by one node
+					val sb = new StringBuilder();
+
+					for (var i = 0; i < nodelist.length; i++) {
+						if (i != 0) {
+							sb.append(separator)
+						}
+						sb.append(nodelist.get(i).getData())
+					}
+					// add string to new map if it doesn't exist already
+					if (!newDoublets.containsKey(sb.toString)) {
+						newDoublets.put(sb.toString, new ArrayList<ArrayList<StringTreeNode>>());
+					}
+
+					newDoublets.get(sb.toString).add(nodelist);
+				}
+			}
+
+			doublets = newDoublets;
+
+			// Abort criterion. If there is any name with more than one element, repeat.
+			abort = true;
+			for (name : doublets.keySet) {
+				if(doublets.get(name).length > 1) abort = false;
+			}
+		}
+
+		return mapping;
+	}
+
+	def private shortenNames() {
+		if (individualMap == null || individualMap.isEmpty()) {
+			constructIndividualNames();
+		}
+		if (this.maxLength == 0) {
+			return;
+		}
+		
+		val max_weight = tree.getWeight();
+
+		while (shortenOneCharacter(tree.getEndNodes(), max_weight)) {
+		}
+
+		shortNamesValid = true;
+	}
+
+	def private boolean shortenOneCharacter(ArrayList<StringTreeNode> endnodes, int max_weight) {
+		/*
+		 * takes all end-nodes of the tree, finds their attached individual chain of nodes, their shortstring and shortens the
+		 * longest chain's cheapest shortstring.
+		 */
+		var max_length = 0;
+		var StringTreeNode max_length_node;
+
+		var names = new ArrayList<String>();
+
+		for (node : endnodes) {
+			// iterates over all endnodes and returns the maximum length of all names.
+			var newname = node.getIndividualName.joinShortStrings();
+			names.add(newname);
+			var length = newname.length();
+			if (length > max_length) {
+				max_length = length;
+				max_length_node = node;
+			}
+		}
+
+		if (max_length < this.maxLength) {
+			return false;
+		}
+
+		var min_cost = Integer.MAX_VALUE;
+		var ShortString best_cut;
+
+		for (node : max_length_node.getIndividualName) // all nodes describing the individual name of this end node
+		{
+			val shortstr = node.shortStringForNode;
+			val current_cost = shortstr.getCutCost();
+
+			var noDoubles = false;
+
+			val node_cost_factor = max_weight - node.getWeight() + 1;
+
+			shortstr.removeCheapestChar();
+
+			val cut_cost = (shortstr.getCutCost() - current_cost) * node_cost_factor;
+
+			val current_name = max_length_node.getIndividualName.joinShortStrings;
+
+			if (!names.contains(current_name)) {
+				noDoubles = true;
+				// do further check to avoid double names only when quick check is okay
+				var doubleCheckArray = new ArrayList<String>();
+				for (n : endnodes) {
+					var newname = n.getIndividualName.joinShortStrings();
+					if (doubleCheckArray.contains(newname)) {
+						noDoubles = false;
+					}
+					doubleCheckArray.add(newname);
+				}
+			}
+
+			if (noDoubles && cut_cost > 0 && cut_cost < min_cost) {
+				min_cost = cut_cost;
+				best_cut = shortstr;
+			}
+
+			shortstr.rollback(); // revert changes
+		}
+
+		if (best_cut == null) {
+			return false;
+		}
+		best_cut.removeCheapestChar(); // reapply best change
+		return true;
+	}
+
+	def private Map<StringTreeNode, ShortString> createShortStringMapping() {
+		val HashMap<StringTreeNode, ShortString> mapping = newHashMap;
+		for (node : tree.getNodes()) {
+			mapping.put(
+				node,
+				new ShortString(node.getData())
+			);
+		}
+
+		return mapping;
+	}
+
+	def private StringTreeNode getNodeForElement(NamedElement elem) {
+		return treeMap.get(elem);
+	}
+
+	def private ShortString getShortStringForNode(StringTreeNode node) {
+		if (node_shortString_map == null || node_shortString_map.isEmpty()) {
+			createShortStringMapping();
+		}
+		return node_shortString_map.get(node);
+	}
+
+	def private ArrayList<StringTreeNode> getIndividualName(StringTreeNode node) {
+		if (individualMap.isEmpty()) {
+			constructIndividualNames();
+		}
+		return individualMap.get(node);
+	}
+
+	def private getShortenedName(StringTreeNode node) {
+		return joinShortStrings(getIndividualName(node));
+	}
+
+	def private getShortenedName(NamedElement elem) {
+		return getShortenedName(getNodeForElement(elem));
+	}
+
+	override asEscapedIdentifier(String string) {
+		asIdentifier(string);
+	}
+
+	override asIdentifier(String string) {
+		string.replaceAll('[^a-z&&[^A-Z&&[^0-9]]]', separator.toString)
+	}
+
+	override isKeyword(String string) {
+		return false;
+	}
+
+	override getShortNameMap(Statechart statechart) {
+		throw new UnsupportedOperationException("TODO: auto-generated method stub")
+	}
+
+	override getShortNameMap(ExecutionFlow flow) {
+		throw new UnsupportedOperationException("TODO: auto-generated method stub")
+	}
+
+	def public getTreeContents() {
+		return tree.getContents();
+	}
+
+	def private List<NamedElement> getNodeElements(StringTreeNode node) {
+		val ArrayList<NamedElement> list = new ArrayList<NamedElement>();
+
+		for (elem : treeMap.keySet()) {
+			if (treeMap.get(elem) == node) {
+				list.add(elem);
+			}
+		}
+
+		return list;
+	}
+
+	def private String joinShortStrings(ArrayList list) {
+		val sb = new StringBuilder();
+		var first = true;
+
+		for (s : list) {
+			var String shortened;
+			if (s instanceof ShortString) {
+				shortened = s.getShortenedString();
+			} else if (s instanceof StringTreeNode) {
+				shortened = s.getShortStringForNode.getShortenedString();
+			}
+			if (shortened.length > 0) {
+				if (first) {
+					sb.append(shortened);
+					first = false;
+				} else {
+					sb.append(separator);
+					sb.append(shortened);
+				}
+			}
+		}
+
+		return sb.toString();
+	}
+
+	def protected suffix(Step it) {
+		var l = new ArrayList<String>();
+
+		switch (it) {
+			case isCheckFunction: {
+				l.add("check");
+			}
+			case isEntryAction: {
+				l.add("enact");
+			}
+			case isExitAction: {
+				l.add("exact");
+			}
+			case isEffect: {
+				l.add("effect");
+			}
+			case isEnterSequence: {
+				l.add("enseq");
+			}
+			case isDeepEnterSequence: {
+				l.add("dhenseq");
+			}
+			case isShallowEnterSequence: {
+				l.add("shenseq");
+			}
+			case isExitSequence: {
+				l.add("exseq");
+			}
+			case isReactSequence: {
+				l.add("react");
+			}
+			default: {
+			}
+		}
+
+		return l;
+	}
+
+	def protected prefix(Step it) {
+		return new ArrayList<String>();
+	}
+
+	def protected prefix(ExecutionState it) {
+		var l = new ArrayList<String>();
+		// l.add(flow.name);
+		return l;
+	}
+
+	def protected suffix(ExecutionState it) {
+		return new ArrayList<String>();
+	}
+
+	def protected prefix(TimeEventSpec it, NamedElement element) {
+		var l = new ArrayList<String>();
+		// l.add(activeFlow.name);
+		return l;
+	}
+
+	def protected suffix(TimeEventSpec it, NamedElement element) {
+		var l = new ArrayList<String>();
+		switch (element) {
+			Statechart: {
+				l.add("tev" + element.timeEventSpecs.indexOf(it));
+			}
+			State: {
+				l.add("tev" + element.timeEventSpecs.indexOf(it));
+			}
+		}
+		return l;
+	}
+
+	def protected prefix(State it) {
+		var l = new ArrayList<String>();
+		// l.add(activeStatechart.name);
+		return l;
+	}
+
+	def protected prefix(Vertex it) {
+		return new ArrayList<String>();
+	}
+
+	def protected suffix(Vertex it) {
+		return new ArrayList<String>();
+	}
+}

+ 4 - 1
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/AllTests.java

@@ -1,5 +1,5 @@
 /** 
- * Copyright (c) 2015 committers of YAKINDU and others. 
+ * Copyright (c) 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 
@@ -29,7 +29,10 @@ import org.junit.runners.Suite.SuiteClasses;
 		ModelSequencerStateVectorTest.class, 
 		ModelSequencerHistoryTest.class,
 		SelfTransitionTest.class,
+		ShortStringTest.class,
 		StatechartEnterExistActionTest.class,
+		StringTreeNodeTest.class,
+		TreeNamingServiceTest.class,
 		DefaultNamingServiceTest.class,
 		NullCallTest.class
 		})

+ 165 - 0
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/ShortStringTest.java

@@ -0,0 +1,165 @@
+/** 
+ * Copyright (c) 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 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ * Contributors:
+ * @author René Beckmann (beckmann@itemis.de)
+ *
+*/
+
+package org.yakindu.sct.model.sexec.transformation.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.yakindu.sct.model.sexec.naming.ShortString;
+
+import com.google.common.primitives.Shorts;
+
+public class ShortStringTest {
+	private ShortString shortstr;
+	
+	@Test
+	public void originalStringTest()
+	{
+		shortstr = new ShortString("ShortStringTest");
+		
+		assertEquals("ShortStringTest", shortstr.getShortenedString());
+	}
+	
+	@Test
+	public void resetTest()
+	{
+		shortstr = new ShortString("Yakindu");
+		
+		shortstr.removeIndex(1);
+		shortstr.removeIndex(3);
+		shortstr.removeIndex(6);
+		
+		assertEquals("Yknd", shortstr.getShortenedString());
+		
+		shortstr.reset();
+		
+		assertEquals("Yakindu", shortstr.getShortenedString());
+	}
+	
+	@Test
+	public void rollBackTest()
+	{
+		shortstr = new ShortString("Yakindu_StatechartTools");
+		
+		shortstr.removeIndex(0);
+		
+		shortstr.rollback();
+		
+		assertEquals("Yakindu_StatechartTools", shortstr.getShortenedString());
+	}
+	
+	@Test
+	public void basicCutCostTest()
+	{
+		shortstr = new ShortString("AAab_7");
+		
+		assertEquals(ShortString.COST_FIRSTLETTER + ShortString.COST_UPPERCASE, shortstr.getBaseCutCost(0));
+		
+		assertEquals(ShortString.COST_UPPERCASE, shortstr.getBaseCutCost(1));
+		
+		assertEquals(ShortString.COST_LOWERCASE_VOCALS, shortstr.getBaseCutCost(2));
+		
+		assertEquals(ShortString.COST_LOWERCASE_CONSONANTS, shortstr.getBaseCutCost(3));
+		
+		assertEquals(ShortString.COST_UNDERSCORE, shortstr.getBaseCutCost(4));
+		
+		assertEquals(ShortString.COST_DIGIT, shortstr.getBaseCutCost(5));
+	}
+	
+	@Test
+	public void cutCostFactorTest()
+	{
+		shortstr = new ShortString("012345");
+		
+		shortstr.removeIndex(0);
+		assertEquals(11, shortstr.getCutCostFactor());
+		
+		shortstr.removeIndex(1);
+		assertEquals(13, shortstr.getCutCostFactor());
+		
+		shortstr.removeIndex(2);
+		assertEquals(15, shortstr.getCutCostFactor());
+		
+		shortstr.removeIndex(3);
+		assertEquals(16, shortstr.getCutCostFactor());
+		
+		shortstr.removeIndex(4);
+		assertEquals(18, shortstr.getCutCostFactor());
+		
+		shortstr.removeIndex(5);
+		assertEquals(20, shortstr.getCutCostFactor());
+	}
+	
+	@Test
+	public void cutRatioTest1()
+	{
+		shortstr = new ShortString("ababababab");
+		shortstr.removeIndex(0);
+		shortstr.removeIndex(2);
+		shortstr.removeIndex(4);
+		shortstr.removeIndex(6);
+		shortstr.removeIndex(8);
+		
+		assertEquals(0.5, shortstr.getCutRatio(), 0.01);
+	}
+	
+	@Test
+	public void costVocalsTest()
+	{
+		shortstr = new ShortString("YakinduStatechartTools");
+		
+		shortstr.removeIndex(1); //a
+		shortstr.removeIndex(3); //i
+		shortstr.removeIndex(6); //u
+		shortstr.removeIndex(9); //a
+		shortstr.removeIndex(11); //e
+		shortstr.removeIndex(14); // a
+		shortstr.removeIndex(18); // o
+		shortstr.removeIndex(19); // o
+		
+		int expectedCost = 8 * ShortString.COST_LOWERCASE_VOCALS * shortstr.getCutCostFactor();
+		
+		assertEquals(expectedCost, shortstr.getCutCost());
+	}
+	
+	@Test
+	public void costFirstLetterTest()
+	{
+		shortstr = new ShortString("all");
+		
+		shortstr.removeIndex(0);
+		
+		int expectedCost = (
+				1 * ShortString.COST_FIRSTLETTER +
+				1 * ShortString.COST_LOWERCASE_VOCALS
+				) * shortstr.getCutCostFactor();
+		
+		assertEquals(expectedCost, shortstr.getCutCost());
+	}
+	
+	@Test
+	public void costFirstUppercaseTest()
+	{
+		shortstr = new ShortString("ATest");
+		
+		shortstr.removeIndex(0);
+		
+		int expectedCost = (
+				1 * ShortString.COST_FIRSTLETTER + 
+				1 * ShortString.COST_UPPERCASE
+				) * shortstr.getCutCostFactor();
+		
+		assertEquals(expectedCost, shortstr.getCutCost());
+	}
+}

+ 273 - 0
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/StringTreeNodeTest.java

@@ -0,0 +1,273 @@
+/** 
+ * Copyright (c) 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 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ * Contributors:
+ * @author René Beckmann (beckmann@itemis.de)
+ *
+*/
+package org.yakindu.sct.model.sexec.transformation.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.yakindu.sct.model.sexec.naming.StringTreeNode;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class StringTreeNodeTest {
+	private StringTreeNode tree;
+
+	@Before
+	public void setupStringTreeNode() {
+		tree = new StringTreeNode();
+	}
+
+	@Test
+	public void stringAddTest() {
+		/*
+		 * Add a few strings where some are substrings of others and check if
+		 * they all exist in the tree.
+		 */
+
+		List<String> testStrings = new ArrayList<String>();
+
+		testStrings.add("Statechart1");
+		testStrings.add("Statechart2");
+		testStrings.add("Statechart1.Region1");
+		testStrings.add("Statechart1.Region2");
+		testStrings.add("Statechart1.Region1.StateA");
+		testStrings.add("Statechart1.Region2.StateA");
+
+		for (String s : testStrings) {
+			tree.addString(s);
+		}
+
+		List<String> treeContents = tree.getContents();
+
+		stringListsEqual(testStrings, treeContents);
+	}
+
+	@Test
+	public void noDoublesTest() {
+		// Add the same string twice, expect it to be in the tree only once.
+		tree.addString("DoubleString");
+		tree.addString("DoubleString");
+
+		assertEquals(1, tree.getContents().size());
+	}
+
+	@Test
+	public void compressTest() {
+		// Add data to the tree, compress it, and compare contents before and
+		// after compressing.
+		tree.addString("PartOne");
+		tree.addString("PartTwo");
+
+		List<String> beforeContents = tree.getContents();
+
+		tree.compress();
+
+		List<String> afterContents = tree.getContents();
+
+		stringListsEqual(beforeContents, afterContents);
+	}
+
+	@Test
+	public void compressNodeTest() {
+		// Add data to the tree, compress it, and check if the nodes match the
+		// expectation.
+		tree.addString("PartOne");
+		tree.addString("PartTwo");
+
+		tree.compress();
+
+		List<StringTreeNode> nodelist = tree.getNodes();
+		List<String> nodecontents = new ArrayList<String>();
+		List<String> expectednodecontents = new ArrayList<String>();
+
+		expectednodecontents.add("Part");
+		expectednodecontents.add("One");
+		expectednodecontents.add("Two");
+		expectednodecontents.add(""); // two end nodes should be present
+		expectednodecontents.add("");
+
+		for (StringTreeNode node : nodelist) {
+			if (node.getData() != null) {
+				nodecontents.add(node.getData());
+			}
+		}
+
+		stringListsEqual(nodecontents, expectednodecontents);
+	}
+
+	@Test
+	public void hasSiblingsTest() {
+		testSiblings("Sc1Reg1StateA", new ArrayList<String>(Arrays.asList("StateB", "StateC")));
+	}
+
+	@Test
+	public void hasNoSiblingsTest() {
+		testSiblings("Sc1Reg2StateA", new ArrayList<String>());
+	}
+
+	@Test
+	public void nodeChainContainedTest() {
+		buildStandardTestTree();
+		String testString = new String("Sc1Reg1StateA");
+		List<StringTreeNode> nodes = tree.getNodeChain(testString);
+
+		StringBuilder builder = new StringBuilder();
+
+		for (StringTreeNode node : nodes) {
+			builder.append(node.getData());
+		}
+
+		assertEquals(testString, builder.toString());
+	}
+
+	@Test
+	public void nodeChainNotContainedTest() {
+		buildStandardTestTree();
+		String testString = new String("Sc1Reg3StateA");
+		List<StringTreeNode> nodes = tree.getNodeChain(testString);
+
+		assertEquals(nodes, null);
+	}
+
+	@Test
+	public void endNodesTest() {
+		buildStandardTestTree();
+		tree.addStringList(new ArrayList<String>(Arrays.asList("Sc1", "Reg1")));
+
+		assertEquals(6, tree.getEndNodes().size());
+	}
+
+	@Test
+	public void distanceTest() {
+		buildStandardTestTree();
+		List<StringTreeNode> nodes1, nodes2, nodes3, nodes4;
+		StringTreeNode testNode1, testNode2, testNode3, testNode4;
+
+		nodes1 = tree.getNodeChain("Sc1Reg1StateA");
+		nodes2 = tree.getNodeChain("Sc1Reg1StateB");
+		nodes3 = tree.getNodeChain("Sc1Reg2StateA");
+		nodes4 = tree.getNodeChain("Sc2Reg1StateA");
+
+		testNode1 = nodes1.get(nodes1.size() - 1); // (Sc1Reg1)State A
+		testNode2 = nodes2.get(nodes2.size() - 1); // (Sc1Reg1)State B
+		testNode3 = nodes3.get(nodes3.size() - 1); // (Sc1Reg2)State A
+		testNode4 = nodes4.get(nodes4.size() - 1); // (Sc2Reg1)State A
+
+		assertEquals(2, testNode1.getDistance(testNode2));
+		assertEquals(4, testNode1.getDistance(testNode3));
+		assertEquals(6, testNode1.getDistance(testNode4));
+	}
+
+	@Test
+	public void navigateTest() {
+		buildStandardTestTree();
+
+		StringTreeNode nextnode = tree.navigate("Sc1");
+
+		assertEquals(true, nextnode != null);
+		assertEquals("Sc1", nextnode.getData());
+
+		nextnode = nextnode.navigate("Reg2");
+
+		assertEquals(true, nextnode != null);
+		assertEquals("Reg2", nextnode.getData());
+
+		nextnode = nextnode.navigate("StateA");
+
+		assertEquals(true, nextnode != null);
+		assertEquals("StateA", nextnode.getData());
+
+		nextnode = nextnode.getParent().getParent();
+
+		assertEquals(true, nextnode != null);
+		assertEquals("Sc1", nextnode.getData());
+	}
+
+	@Test
+	public void childrenContentTest() {
+		buildStandardTestTree();
+
+		StringTreeNode nextnode = tree.navigate("Sc1");
+
+		ArrayList<String> expectedChildren = new ArrayList<String>(Arrays.asList("Reg1", "Reg2"));
+
+		stringListsEqual(expectedChildren, nextnode.getChildrenContents());
+	}
+
+	@Test
+	public void deletionTest() {
+		buildStandardTestTree();
+
+		tree.navigate("Sc1").navigate("Reg2").delete();
+
+		ArrayList<String> expectedContents = new ArrayList<String>(
+				Arrays.asList("Sc1Reg1StateA", "Sc1Reg1StateB", "Sc1Reg1StateC", "Sc2Reg1StateA"));
+
+		stringListsEqual(expectedContents, tree.getContents());
+	}
+
+	@Test
+	public void addStringListReturnTest1() {
+		List<String> list = new ArrayList<String>(Arrays.asList("Un", "Deux", "Trois", "Quatre"));
+		StringTreeNode testNode = tree.addStringList(list);
+
+		assertEquals("UnDeuxTroisQuatre", testNode.getContentUpwards());
+	}
+
+	@Test
+	public void addStringListReturnTest2() {
+		List<String> list1 = new ArrayList<String>(Arrays.asList("Un", "Deux", "Trois", "Quatre"));
+		List<String> list2 = new ArrayList<String>(list1);
+		list2.add("Cinq");
+
+		tree.addStringList(list2);
+
+		StringTreeNode testNode = tree.addStringList(list1);
+
+		assertEquals("UnDeuxTroisQuatre", testNode.getContentUpwards());
+	}
+
+	@Test
+	public void weightTest() {
+		buildStandardTestTree();
+
+		assertEquals(15, tree.getWeight());
+	}
+
+	private void testSiblings(String testString, List<String> expectedSiblings) {
+		buildStandardTestTree();
+		stringListsEqual(tree.getSiblings(testString), expectedSiblings);
+	}
+
+	private void buildStandardTestTree() {
+		/*
+		 * StateA / root-Sc1-Reg1-StateB \ \ \ \ \ StateC \ \ \ Reg2-StateA \
+		 * Sc2-Reg1-StateA
+		 */
+		tree.addStringList(new ArrayList<String>(Arrays.asList("Sc1", "Reg1", "StateA")));
+		tree.addStringList(new ArrayList<String>(Arrays.asList("Sc1", "Reg1", "StateB")));
+		tree.addStringList(new ArrayList<String>(Arrays.asList("Sc1", "Reg1", "StateC")));
+		tree.addStringList(new ArrayList<String>(Arrays.asList("Sc1", "Reg2", "StateA")));
+		tree.addStringList(new ArrayList<String>(Arrays.asList("Sc2", "Reg1", "StateA")));
+	}
+
+	private void stringListsEqual(List<String> onelist, List<String> otherlist) {
+		java.util.Collections.sort(onelist, Collator.getInstance());
+		java.util.Collections.sort(otherlist, Collator.getInstance());
+		assertEquals(onelist, otherlist);
+	}
+}

+ 291 - 0
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/TreeNamingServiceTest.java

@@ -0,0 +1,291 @@
+/** 
+ * Copyright (c) 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 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ * Contributors:
+ * @author René Beckmann (beckmann@itemis.de)
+ *
+*/
+package org.yakindu.sct.model.sexec.transformation.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.yakindu.sct.model.sexec.ExecutionFlow;
+import org.yakindu.sct.model.sexec.ExecutionState;
+import org.yakindu.sct.model.sexec.Step;
+import org.yakindu.sct.model.sexec.extensions.SExecExtensions;
+import org.yakindu.sct.model.sexec.naming.INamingService;
+import org.yakindu.sct.model.sexec.naming.TreeNamingService;
+import org.yakindu.sct.model.sexec.transformation.FlowOptimizer;
+import org.yakindu.sct.model.sgraph.State;
+import org.yakindu.sct.model.sgraph.Statechart;
+import org.yakindu.sct.test.models.SCTUnitTestModels;
+
+import com.google.inject.Inject;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class TreeNamingServiceTest extends ModelSequencerTest {
+	@Inject
+	protected SCTUnitTestModels testModels;
+
+	@Inject
+	FlowOptimizer optimizer;
+
+	@Inject
+	protected TreeNamingService statechartNamingService;
+
+	@Inject
+	protected TreeNamingService executionflowNamingService;
+
+	private List<Statechart> statecharts;
+
+	@Before
+	public void setupNamingService() {
+		statecharts = Collections.emptyList();
+
+		try {
+			statecharts = testModels.loadAllStatecharts();
+		} catch (Exception e) {
+			fail(e.getMessage());
+		}
+
+		optimizer.inlineReactions(false);
+		optimizer.inlineExitActions(false);
+		optimizer.inlineEntryActions(true);
+		optimizer.inlineEnterSequences(true);
+		optimizer.inlineExitSequences(true);
+		optimizer.inlineChoices(true);
+		optimizer.inlineEntries(true);
+		optimizer.inlineEnterRegion(true);
+		optimizer.inlineExitRegion(true);
+
+		// TODO: Why does PerformanceTest doesn't work?
+		Statechart statecharttoRemove = null;
+		for (Statechart sct : statecharts) {
+			if (sct.getName().equals("PerformanceTest")) {
+				statecharttoRemove = sct;
+			}
+		}
+		statecharts.remove(statecharttoRemove);
+	}
+
+	@Test
+	public void testDefaultNamingServiceState_NoDoubles() {
+
+		for (Statechart statechart : statecharts) {
+
+			// Transform statechart
+			ExecutionFlow flow = sequencer.transform(statechart);
+			flow = optimizer.transform(flow);
+
+			List<String> names = new ArrayList<String>();
+
+			executionflowNamingService.setMaxLength(15);
+			executionflowNamingService.setSeparator('_');
+
+			// Initialize naming services for statechart and ExecutionFlow
+			long t0 = System.currentTimeMillis();
+			executionflowNamingService.initializeNamingService(flow);
+			executionflowNamingService.test_printTreeContents();
+			System.out.print("Time needed for initialization [ms]: ");
+			System.out.println(System.currentTimeMillis() - t0);
+			System.out.println("Generated names:");
+			for (ExecutionState state : flow.getStates()) {
+				String name = executionflowNamingService.getShortName(state);
+				if (names.contains(name)) {
+					System.out.println("Conflicting name: " + name);
+					for (String n : names) {
+						System.out.println(n);
+					}
+				}
+				assertEquals(names.contains(name), false);
+				names.add(name);
+				System.out.println(name);
+			}
+			System.out.println();
+		}
+	}
+
+	@Test
+	public void nameLengthTest31() {
+		nameLengthTest(31);
+	}
+
+	@Test
+	public void nameLengthTest20() {
+		nameLengthTest(20);
+	}
+
+	@Test
+	public void nameLengthTest15() {
+		nameLengthTest(15);
+	}
+
+	@Test
+	public void nameLengthTest10() {
+		nameLengthTest(10);
+	}
+
+	@Test
+	public void nameLengthTest8() {
+		nameLengthTest(8);
+	}
+
+	@Test
+	public void optimizerCombinationsTest() {
+		Statechart toTest = null;
+
+		for (Statechart statechart : statecharts) {
+			if (statechart.getName().equals("DeepEntry")) {
+				toTest = statechart;
+			}
+		}
+
+		assertEquals(true, toTest != null);
+
+		ExecutionFlow flow = sequencer.transform(toTest);
+
+		executionflowNamingService.setMaxLength(0);
+		executionflowNamingService.setSeparator('_');
+
+		for (int i = 0; i < (1 << 9); i++) {
+			optimizer.inlineReactions((i & (1)) != 0);
+			optimizer.inlineExitActions((i & (1 << 1)) != 0);
+			optimizer.inlineEntryActions((i & (1 << 2)) != 0);
+			optimizer.inlineEnterSequences((i & (1 << 3)) != 0);
+			optimizer.inlineExitSequences((i & (1 << 4)) != 0);
+			optimizer.inlineChoices((i & (1 << 5)) != 0);
+			optimizer.inlineEntries((i & (1 << 6)) != 0);
+			optimizer.inlineEnterRegion((i & (1 << 7)) != 0);
+			optimizer.inlineExitRegion((i & (1 << 8)) != 0);
+
+			ExecutionFlow optimizedflow = optimizer.transform(flow);
+
+			List<String> names = new ArrayList<String>();
+
+			executionflowNamingService.initializeNamingService(optimizedflow);
+			for (ExecutionState state : flow.getStates()) {
+				String name = executionflowNamingService.getShortName(state);
+				assertEquals(names.contains(name), false);
+				names.add(name);
+			}
+		}
+	}
+
+	@Test
+	public void statechartTest1() {
+		Statechart toTest = getNamingServiceStatechart();
+
+		List<String> names = new ArrayList<String>();
+
+		List<String> expectedNames = new ArrayList<String>(
+				Arrays.asList("main_region_StateA", "main_region_StateB", "second_region_StateA", "third_region_StateA",
+						"second_region_StateA_AnotherRegion_StateA", "second_region_StateA_AnotherRegion_StateB",
+						"third_region_StateA_AnotherRegion_StateA", "third_region_StateA_AnotherRegion_StateB"));
+
+		ExecutionFlow flow = optimizer.transform(sequencer.transform(toTest));
+
+		executionflowNamingService.setMaxLength(0);
+		executionflowNamingService.setSeparator('_');
+		executionflowNamingService.initializeNamingService(flow);
+
+		statechartNamingService.setMaxLength(0);
+		statechartNamingService.setSeparator('_');
+		statechartNamingService.initializeNamingService(toTest);
+
+		for (ExecutionState state : flow.getStates()) {
+			String name = executionflowNamingService.getShortName(state);
+			assertEquals(names.contains(name), false);
+			assertEquals(name, statechartNamingService.getShortName(state));
+			names.add(name);
+		}
+
+		stringListsEqual(expectedNames, names);
+	}
+
+	@Test
+	public void statechartTest2() {
+		Statechart toTest = getNamingServiceStatechart();
+
+		List<String> names = new ArrayList<String>();
+
+		// these names are shorter than 15 characters because there are more
+		// elements containing these names, e.g. state actions
+		List<String> expectedNames = new ArrayList<String>(Arrays.asList("mgn_SA", "mgn_StteB", "s_S", "t_S",
+				"t_S_AR_SA", "t_S_AR_StB", "s_S_AR_SA", "s_S_AR_StB"));
+
+		ExecutionFlow flow = optimizer.transform(sequencer.transform(toTest));
+
+		executionflowNamingService.setMaxLength(15);
+		executionflowNamingService.setSeparator('_');
+
+		executionflowNamingService.initializeNamingService(flow);
+
+		for (ExecutionState state : flow.getStates()) {
+			String name = executionflowNamingService.getShortName(state);
+			assertEquals(names.contains(name), false);
+			names.add(name);
+		}
+
+		stringListsEqual(expectedNames, names);
+	}
+
+	private Statechart getNamingServiceStatechart() {
+		Statechart toTest = null;
+
+		for (Statechart statechart : statecharts) {
+			if (statechart.getName().equals("namingTest")) {
+				toTest = statechart;
+			}
+		}
+
+		assertEquals(true, toTest != null);
+
+		return toTest;
+	}
+
+	private void nameLengthTest(int maxLength) {
+		int num_statecharts = statecharts.size();
+		long cumulated_time = 0L;
+		for (Statechart statechart : statecharts) {
+
+			// Transform statechart
+			ExecutionFlow flow = sequencer.transform(statechart);
+			flow = optimizer.transform(flow);
+
+			List<String> names = new ArrayList<String>();
+
+			executionflowNamingService.setMaxLength(maxLength);
+			executionflowNamingService.setSeparator('_');
+
+			long t0 = System.currentTimeMillis();
+			executionflowNamingService.initializeNamingService(flow);
+			cumulated_time += System.currentTimeMillis() - t0;
+			for (ExecutionState state : flow.getStates()) {
+				String name = executionflowNamingService.getShortName(state);
+				assertEquals(names.contains(name), false);
+				assertEquals(true, name.length() <= maxLength);
+				names.add(name);
+			}
+		}
+
+		System.out.print("Average time for initialization [ms]: ");
+		System.out.println((float) cumulated_time / (float) num_statecharts);
+	}
+
+	private void stringListsEqual(List<String> onelist, List<String> otherlist) {
+		java.util.Collections.sort(onelist, Collator.getInstance());
+		java.util.Collections.sort(otherlist, Collator.getInstance());
+		assertEquals(onelist, otherlist);
+	}
+}

+ 126 - 125
test-plugins/org.yakindu.sct.test.models/src/org/yakindu/sct/test/models/SCTUnitTestModels.java

@@ -1,125 +1,126 @@
-/**
- * Copyright (c) 2014 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
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     committers of YAKINDU - initial API and implementation
- */
-package org.yakindu.sct.test.models;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.yakindu.sct.model.sgraph.Statechart;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-
-/**
- * 
- * @author andreas muelder - Initial contribution and API
- * 
- */
-public class SCTUnitTestModels extends AbstractTestModelsUtil {
-
-	private static final String TESTMODEL_DIR = "org.yakindu.sct.test.models/testmodels/SCTUnit/";
-	public static final String ALWAYS_ONCYCLE = "AlwaysOncycle.sct";
-	public static final String ASSIGNMENT_AS_EXPRESSION ="AssignmentAsExpression.sct";
-	public static final String BIT_EXPRESSIONS = "BitExpressions.sct";
-	public static final String BOOLEAN_EXPRESSIONS = "BooleanExpressions.sct";
-	public static final String CAST_EXPRESSIONS = "CastExpressions.sct";
-	public static final String CHOICE = "Choice.sct";
-	public static final String C_KEYWORDS_M = "CKeywords.sct";
-	public static final String CONDITIONAL_EXPRESSIONS = "ConditionalExpressions.sct";
-	public static final String CONSTANTS = "Constants.sct";
-	public static final String DECLARATIONS = "Declarations.sct";
-	public static final String DEEP_ENTRY = "DeepEntry.sct";
-	public static final String DEEP_HISTORY = "DeepHistory.sct";
-	public static final String DYNAMIC_CHOICE = "DynamicChoice.sct";
-	public static final String ENTER_STATE = "EnterState.sct";
-	public static final String ENTRY_CHOICE = "EntryChoice.sct";
-	public static final String EXIT_ON_SELF_TRANSITION = "ExitOnSelfTransition.sct";
-	public static final String EXIT_STATE = "ExitState.sct";
-	public static final String EXIT_STATECHART = "ExitStatechart.sct /* don't test currently */";
-	public static final String FEATURE_CALLS = "FeatureCalls.sct";
-	public static final String GUARD = "Guard.sct";
-	public static final String GUARDED_ENTRY = "GuardedEntry.sct";
-	public static final String GUARDED_EXIT = "GuardedExit.sct";
-	public static final String HISTORY_WITH_EXIT_POINT = "HistoryWithExitPoint.sct";
-	public static final String HISTORY_WITHOUT_INITIAL_STEP = "HistoryWithoutInitialStep.sct";
-	public static final String IN_EVENT_LIFE_CYCLE = "InEventLifeCycle.sct";
-	public static final String INTEGER_EXPRESSIONS = "IntegerExpressions.sct";
-	public static final String INTERNAT_EVENT_LIFE_CYCLE = "InternalEventLifeCycle.sct";
-	public static final String JAVA_KEYWORDS_M = "JavaKeywords.sct";
-	public static final String LOCAL_REACTIONS = "LocalReactions.sct";
-	public static final String LOGICAL_AND = "LogicalAnd.sct";
-	public static final String LOGICAL_OR = "LogicalOr.sct";
-	public static final String NAMED_INTERFACE_ACCESS = "NamedInterfaceAccess.sct";
-	public static final String NULL_CHECK = "NullCheck.sct";
-	public static final String OPERATIONS = "Operations.sct";
-	public static final String OUT_EVENT_LIFE_CYCLE = "OutEventLifeCycle.sct";
-	public static final String PARENTHESIS = "Parenthesis.sct";
-	public static final String PERFORMANCE_TEST = "PerformanceTest.sct";
-	public static final String PRIORITY_VALUES = "PriorityValues.sct";
-	public static final String RAISE_EVENTS = "RaiseEvent.sct";
-	public static final String REAL_EXPRESSIONS = "RealExpressions.sct";
-	public static final String SAME_NAME_DIFFERENT_REGION = "SameNameDifferentRegion.sct";
-	public static final String SHALLOW_HISTORY = "ShallowHistory.sct";
-	public static final String SIMPLE_EVENT = "SimpleEvent.sct";
-	public static final String SIMPLE_HIERACHY = "SimpleHierachy.sct";
-	public static final String STATECHART_LOCAL_REACTIONS = "StatechartLocalReactions.sct";	
-	public static final String STATE_ACTIVE = "StateIsActive.sct";
-	public static final String STATIC_CHOICE = "StaticChoice.sct";
-	public static final String STEXT_KEYWORDS_IN_STATES_AND_REGIONS = "STextKeywordsInStatesAndRegions.sct";
-	public static final String STRING_EXPRESSIONS = "StringExpressions.sct";
-	public static final String SYNC_JOIN = "SyncJoin.sct";
-	public static final String SYNC_FORK = "SyncFork.sct";
-	public static final String TIMED_TRANSITIONS = "TimedTransitions.sct";
-	public static final String TRANSITIONS_WITHOUT_CONDITION = "TransitionWithoutCondition.sct";
-	public static final String TRIFFER_GUARD_EXPRESSIONS = "TriggerGuardExpressions.sct";
-	public static final String TYPE_ALIAS = "TypeAlias.sct";
-	public static final String VALUED_EVENTS = "ValuedEvents.sct";
-	
-	@Override
-	public String getModelDirectory() {
-		return TESTMODEL_DIR;
-	}
-
-	public List<Statechart> loadAllStatecharts() throws Exception {
-		List<Statechart> result = new ArrayList<Statechart>();
-		Field[] fields = getClass().getFields();
-		for (Field field : fields) {
-			String value = (String) field.get(this);
-			if (value.endsWith(".sct")) {
-				result.add(loadStatechartFromResource(value));
-			}
-		}
-		return result;
-	}
-	public static Iterable<Object[]> parameterizedTestData() throws Exception {
-		SCTUnitTestModels models = new SCTUnitTestModels();
-		List<Statechart> all = models.loadAllStatecharts();
-		return Iterables.transform(all, new Function<Statechart, Object[]>() {
-			public Object[] apply(Statechart input) {
-				return new Object[] { input };
-			}
-		});
-	}
-	
-	public Statechart loadStatechartByFilename(String requestedStatechart) throws Exception {
-		Statechart result = null;		
-		Field[] fields = getClass().getFields();
-		for (Field field : fields) {			
-			String value = (String) field.get(this);
-			if (value.endsWith(requestedStatechart)) {
-				result  = (loadStatechartFromResource(value));
-				break;
-			}			
-		}
-		return result;
-	}
-}
+/**
+ * Copyright (c) 2014 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     committers of YAKINDU - initial API and implementation
+ */
+package org.yakindu.sct.test.models;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.yakindu.sct.model.sgraph.Statechart;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+
+/**
+ * 
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+public class SCTUnitTestModels extends AbstractTestModelsUtil {
+
+	private static final String TESTMODEL_DIR = "org.yakindu.sct.test.models/testmodels/SCTUnit/";
+	public static final String ALWAYS_ONCYCLE = "AlwaysOncycle.sct";
+	public static final String ASSIGNMENT_AS_EXPRESSION = "AssignmentAsExpression.sct";
+	public static final String BIT_EXPRESSIONS = "BitExpressions.sct";
+	public static final String BOOLEAN_EXPRESSIONS = "BooleanExpressions.sct";
+	public static final String CAST_EXPRESSIONS = "CastExpressions.sct";
+	public static final String CHOICE = "Choice.sct";
+	public static final String C_KEYWORDS_M = "CKeywords.sct";
+	public static final String CONDITIONAL_EXPRESSIONS = "ConditionalExpressions.sct";
+	public static final String CONSTANTS = "Constants.sct";
+	public static final String DECLARATIONS = "Declarations.sct";
+	public static final String DEEP_ENTRY = "DeepEntry.sct";
+	public static final String DEEP_HISTORY = "DeepHistory.sct";
+	public static final String DYNAMIC_CHOICE = "DynamicChoice.sct";
+	public static final String ENTER_STATE = "EnterState.sct";
+	public static final String ENTRY_CHOICE = "EntryChoice.sct";
+	public static final String EXIT_ON_SELF_TRANSITION = "ExitOnSelfTransition.sct";
+	public static final String EXIT_STATE = "ExitState.sct";
+	public static final String EXIT_STATECHART = "ExitStatechart.sct /* don't test currently */";
+	public static final String FEATURE_CALLS = "FeatureCalls.sct";
+	public static final String GUARD = "Guard.sct";
+	public static final String GUARDED_ENTRY = "GuardedEntry.sct";
+	public static final String GUARDED_EXIT = "GuardedExit.sct";
+	public static final String HISTORY_WITH_EXIT_POINT = "HistoryWithExitPoint.sct";
+	public static final String HISTORY_WITHOUT_INITIAL_STEP = "HistoryWithoutInitialStep.sct";
+	public static final String IN_EVENT_LIFE_CYCLE = "InEventLifeCycle.sct";
+	public static final String INTEGER_EXPRESSIONS = "IntegerExpressions.sct";
+	public static final String INTERNAT_EVENT_LIFE_CYCLE = "InternalEventLifeCycle.sct";
+	public static final String JAVA_KEYWORDS_M = "JavaKeywords.sct";
+	public static final String LOCAL_REACTIONS = "LocalReactions.sct";
+	public static final String LOGICAL_AND = "LogicalAnd.sct";
+	public static final String LOGICAL_OR = "LogicalOr.sct";
+	public static final String NAMED_INTERFACE_ACCESS = "NamedInterfaceAccess.sct";
+	public static final String NAMING_TEST = "NamingTest.sct";
+	public static final String NULL_CHECK = "NullCheck.sct";
+	public static final String OPERATIONS = "Operations.sct";
+	public static final String OUT_EVENT_LIFE_CYCLE = "OutEventLifeCycle.sct";
+	public static final String PARENTHESIS = "Parenthesis.sct";
+	public static final String PERFORMANCE_TEST = "PerformanceTest.sct";
+	public static final String PRIORITY_VALUES = "PriorityValues.sct";
+	public static final String RAISE_EVENTS = "RaiseEvent.sct";
+	public static final String REAL_EXPRESSIONS = "RealExpressions.sct";
+	public static final String SAME_NAME_DIFFERENT_REGION = "SameNameDifferentRegion.sct";
+	public static final String SHALLOW_HISTORY = "ShallowHistory.sct";
+	public static final String SIMPLE_EVENT = "SimpleEvent.sct";
+	public static final String SIMPLE_HIERACHY = "SimpleHierachy.sct";
+	public static final String STATECHART_LOCAL_REACTIONS = "StatechartLocalReactions.sct";
+	public static final String STATE_ACTIVE = "StateIsActive.sct";
+	public static final String STATIC_CHOICE = "StaticChoice.sct";
+	public static final String STEXT_KEYWORDS_IN_STATES_AND_REGIONS = "STextKeywordsInStatesAndRegions.sct";
+	public static final String STRING_EXPRESSIONS = "StringExpressions.sct";
+	public static final String SYNC_JOIN = "SyncJoin.sct";
+	public static final String SYNC_FORK = "SyncFork.sct";
+	public static final String TIMED_TRANSITIONS = "TimedTransitions.sct";
+	public static final String TRANSITIONS_WITHOUT_CONDITION = "TransitionWithoutCondition.sct";
+	public static final String TRIFFER_GUARD_EXPRESSIONS = "TriggerGuardExpressions.sct";
+	public static final String TYPE_ALIAS = "TypeAlias.sct";
+	public static final String VALUED_EVENTS = "ValuedEvents.sct";
+
+	@Override
+	public String getModelDirectory() {
+		return TESTMODEL_DIR;
+	}
+
+	public List<Statechart> loadAllStatecharts() throws Exception {
+		List<Statechart> result = new ArrayList<Statechart>();
+		Field[] fields = getClass().getFields();
+		for (Field field : fields) {
+			String value = (String) field.get(this);
+			if (value.endsWith(".sct")) {
+				result.add(loadStatechartFromResource(value));
+			}
+		}
+		return result;
+	}
+	public static Iterable<Object[]> parameterizedTestData() throws Exception {
+		SCTUnitTestModels models = new SCTUnitTestModels();
+		List<Statechart> all = models.loadAllStatecharts();
+		return Iterables.transform(all, new Function<Statechart, Object[]>() {
+			public Object[] apply(Statechart input) {
+				return new Object[]{input};
+			}
+		});
+	}
+
+	public Statechart loadStatechartByFilename(String requestedStatechart) throws Exception {
+		Statechart result = null;
+		Field[] fields = getClass().getFields();
+		for (Field field : fields) {
+			String value = (String) field.get(this);
+			if (value.endsWith(requestedStatechart)) {
+				result = (loadStatechartFromResource(value));
+				break;
+			}
+		}
+		return result;
+	}
+}

+ 389 - 0
test-plugins/org.yakindu.sct.test.models/testmodels/SCTUnit/NamingTest.sct

@@ -0,0 +1,389 @@
+<?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="_Pd8FQG99EeaVpdzj7q6bjg" specification="interface:&#xA;// Define events and&#xA;// and variables here" name="namingTest">
+    <regions xmi:id="_Pd96cm99EeaVpdzj7q6bjg" name="main region">
+      <vertices xsi:type="sgraph:Entry" xmi:id="_PepP4G99EeaVpdzj7q6bjg">
+        <outgoingTransitions xmi:id="_PethUW99EeaVpdzj7q6bjg" target="_PerFFG99EeaVpdzj7q6bjg"/>
+      </vertices>
+      <vertices xsi:type="sgraph:State" xmi:id="_PerFFG99EeaVpdzj7q6bjg" name="StateA" incomingTransitions="_PethUW99EeaVpdzj7q6bjg">
+        <outgoingTransitions xmi:id="_02w84G99EeaVpdzj7q6bjg" specification="oncycle" target="_ze2uwG99EeaVpdzj7q6bjg"/>
+      </vertices>
+      <vertices xsi:type="sgraph:State" xmi:id="_ze2uwG99EeaVpdzj7q6bjg" name="StateB" incomingTransitions="_02w84G99EeaVpdzj7q6bjg"/>
+    </regions>
+    <regions xmi:id="_TUs7cG99EeaVpdzj7q6bjg" name="second_region">
+      <vertices xsi:type="sgraph:Entry" xmi:id="_TUs7cW99EeaVpdzj7q6bjg">
+        <outgoingTransitions xmi:id="_TUs7cm99EeaVpdzj7q6bjg" target="_TUtigG99EeaVpdzj7q6bjg"/>
+      </vertices>
+      <vertices xsi:type="sgraph:State" xmi:id="_TUtigG99EeaVpdzj7q6bjg" name="StateA" incomingTransitions="_TUs7cm99EeaVpdzj7q6bjg">
+        <regions xmi:id="_dFXkQG99EeaVpdzj7q6bjg" name="AnotherRegion">
+          <vertices xsi:type="sgraph:State" xmi:id="_eh3XcG99EeaVpdzj7q6bjg" name="StateA" incomingTransitions="_gk8pgG99EeaVpdzj7q6bjg">
+            <outgoingTransitions xmi:id="_kKPVMG99EeaVpdzj7q6bjg" specification="oncycle" target="_jFNm0G99EeaVpdzj7q6bjg"/>
+          </vertices>
+          <vertices xsi:type="sgraph:Entry" xmi:id="_fmk8wG99EeaVpdzj7q6bjg">
+            <outgoingTransitions xmi:id="_gk8pgG99EeaVpdzj7q6bjg" specification="" target="_eh3XcG99EeaVpdzj7q6bjg"/>
+          </vertices>
+          <vertices xsi:type="sgraph:State" xmi:id="_jFNm0G99EeaVpdzj7q6bjg" name="StateB" incomingTransitions="_kKPVMG99EeaVpdzj7q6bjg"/>
+        </regions>
+      </vertices>
+    </regions>
+    <regions xmi:id="_q_v_AG9-EeaVpdzj7q6bjg" name="third_region">
+      <vertices xsi:type="sgraph:Entry" xmi:id="_q_v_AW9-EeaVpdzj7q6bjg">
+        <outgoingTransitions xmi:id="_q_v_Am9-EeaVpdzj7q6bjg" target="_q_wmEG9-EeaVpdzj7q6bjg"/>
+      </vertices>
+      <vertices xsi:type="sgraph:State" xmi:id="_q_wmEG9-EeaVpdzj7q6bjg" name="StateA" incomingTransitions="_q_v_Am9-EeaVpdzj7q6bjg">
+        <regions xmi:id="_q_xNIG9-EeaVpdzj7q6bjg" name="AnotherRegion">
+          <vertices xsi:type="sgraph:State" xmi:id="_q_xNIW9-EeaVpdzj7q6bjg" name="StateA" incomingTransitions="_q_ybQm9-EeaVpdzj7q6bjg">
+            <outgoingTransitions xmi:id="_q_x0MG9-EeaVpdzj7q6bjg" specification="oncycle" target="_q_ybQ29-EeaVpdzj7q6bjg"/>
+          </vertices>
+          <vertices xsi:type="sgraph:Entry" xmi:id="_q_ybQW9-EeaVpdzj7q6bjg">
+            <outgoingTransitions xmi:id="_q_ybQm9-EeaVpdzj7q6bjg" specification="" target="_q_xNIW9-EeaVpdzj7q6bjg"/>
+          </vertices>
+          <vertices xsi:type="sgraph:State" xmi:id="_q_ybQ29-EeaVpdzj7q6bjg" name="StateB" incomingTransitions="_q_x0MG9-EeaVpdzj7q6bjg"/>
+        </regions>
+      </vertices>
+    </regions>
+  </sgraph:Statechart>
+  <notation:Diagram xmi:id="_Pd96cG99EeaVpdzj7q6bjg" type="org.yakindu.sct.ui.editor.editor.StatechartDiagramEditor" element="_Pd8FQG99EeaVpdzj7q6bjg" measurementUnit="Pixel">
+    <children xmi:id="_PeF2QG99EeaVpdzj7q6bjg" type="Region" element="_Pd96cm99EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_PemzoG99EeaVpdzj7q6bjg" type="RegionName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_PemzoW99EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_Pemzom99EeaVpdzj7q6bjg"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_PenasG99EeaVpdzj7q6bjg" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+        <children xmi:id="_Pep28G99EeaVpdzj7q6bjg" type="Entry" element="_PepP4G99EeaVpdzj7q6bjg">
+          <children xmi:id="_PeqeAG99EeaVpdzj7q6bjg" type="BorderItemLabelContainer">
+            <children xsi:type="notation:DecorationNode" xmi:id="_PerFEG99EeaVpdzj7q6bjg" type="BorderItemLabel">
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_PerFEW99EeaVpdzj7q6bjg"/>
+              <layoutConstraint xsi:type="notation:Location" xmi:id="_PerFEm99EeaVpdzj7q6bjg"/>
+            </children>
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_PeqeAW99EeaVpdzj7q6bjg" fontName="Verdana" lineColor="4210752"/>
+            <layoutConstraint xsi:type="notation:Bounds" xmi:id="_PeqeAm99EeaVpdzj7q6bjg"/>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_Pep28W99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+          <styles xsi:type="notation:NamedStyle" xmi:id="_Pep28m99EeaVpdzj7q6bjg" name="allowColors"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_PerFE299EeaVpdzj7q6bjg" x="70" y="20"/>
+        </children>
+        <children xmi:id="_PersIG99EeaVpdzj7q6bjg" type="State" element="_PerFFG99EeaVpdzj7q6bjg">
+          <children xsi:type="notation:DecorationNode" xmi:id="_PesTMG99EeaVpdzj7q6bjg" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_PesTMW99EeaVpdzj7q6bjg"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_PesTMm99EeaVpdzj7q6bjg"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_Pes6QG99EeaVpdzj7q6bjg" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_Pes6QW99EeaVpdzj7q6bjg" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_Pes6Qm99EeaVpdzj7q6bjg"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_Pes6Q299EeaVpdzj7q6bjg" type="StateFigureCompartment"/>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_PersIW99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_PersIm99EeaVpdzj7q6bjg"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_Pes6RG99EeaVpdzj7q6bjg" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_PethUG99EeaVpdzj7q6bjg" x="40" y="80"/>
+        </children>
+        <children xmi:id="_ze6ZIG99EeaVpdzj7q6bjg" type="State" element="_ze2uwG99EeaVpdzj7q6bjg">
+          <children xsi:type="notation:DecorationNode" xmi:id="_ze7AMG99EeaVpdzj7q6bjg" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_ze7AMW99EeaVpdzj7q6bjg"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_ze7AMm99EeaVpdzj7q6bjg"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_ze7AM299EeaVpdzj7q6bjg" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_ze7ANG99EeaVpdzj7q6bjg" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_ze7nQG99EeaVpdzj7q6bjg"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_ze8OUG99EeaVpdzj7q6bjg" type="StateFigureCompartment"/>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_ze6ZIW99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_ze6ZIm99EeaVpdzj7q6bjg"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_ze8OUW99EeaVpdzj7q6bjg" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_ze6ZI299EeaVpdzj7q6bjg" x="254" y="80"/>
+        </children>
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_PenasW99EeaVpdzj7q6bjg"/>
+      </children>
+      <styles xsi:type="notation:ShapeStyle" xmi:id="_PeF2QW99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_Peoo0G99EeaVpdzj7q6bjg" x="220" y="10" width="400" height="400"/>
+    </children>
+    <children xsi:type="notation:Shape" xmi:id="_Pev9kG99EeaVpdzj7q6bjg" type="StatechartText" fontName="Verdana" lineColor="4210752">
+      <children xsi:type="notation:DecorationNode" xmi:id="_PewkoG99EeaVpdzj7q6bjg" type="StatechartName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_PewkoW99EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_Pewkom99EeaVpdzj7q6bjg"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_Pewko299EeaVpdzj7q6bjg" type="StatechartTextExpression" fontName="Verdana" lineColor="4210752">
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_PewkpG99EeaVpdzj7q6bjg"/>
+      </children>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_PexLsG99EeaVpdzj7q6bjg" x="10" y="10" width="200" height="400"/>
+    </children>
+    <children xmi:id="_TUoqAG99EeaVpdzj7q6bjg" type="Region" element="_TUs7cG99EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_TUoqAW99EeaVpdzj7q6bjg" type="RegionName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_TUoqAm99EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_TUoqA299EeaVpdzj7q6bjg"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_TUoqBG99EeaVpdzj7q6bjg" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+        <children xmi:id="_TUoqBW99EeaVpdzj7q6bjg" type="Entry" element="_TUs7cW99EeaVpdzj7q6bjg">
+          <children xmi:id="_TUoqBm99EeaVpdzj7q6bjg" type="BorderItemLabelContainer">
+            <children xsi:type="notation:DecorationNode" xmi:id="_TUoqB299EeaVpdzj7q6bjg" type="BorderItemLabel">
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_TUoqCG99EeaVpdzj7q6bjg"/>
+              <layoutConstraint xsi:type="notation:Location" xmi:id="_TUoqCW99EeaVpdzj7q6bjg"/>
+            </children>
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_TUoqCm99EeaVpdzj7q6bjg" fontName="Verdana" lineColor="4210752"/>
+            <layoutConstraint xsi:type="notation:Bounds" xmi:id="_TUoqC299EeaVpdzj7q6bjg"/>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_TUoqDG99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+          <styles xsi:type="notation:NamedStyle" xmi:id="_TUoqDW99EeaVpdzj7q6bjg" name="allowColors"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_TUoqDm99EeaVpdzj7q6bjg" x="70" y="20" width="15" height="15"/>
+        </children>
+        <children xmi:id="_TUoqD299EeaVpdzj7q6bjg" type="State" element="_TUtigG99EeaVpdzj7q6bjg">
+          <children xsi:type="notation:DecorationNode" xmi:id="_TUoqEG99EeaVpdzj7q6bjg" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_TUoqEW99EeaVpdzj7q6bjg"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_TUoqEm99EeaVpdzj7q6bjg"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_TUoqE299EeaVpdzj7q6bjg" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_TUoqFG99EeaVpdzj7q6bjg" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_TUoqFW99EeaVpdzj7q6bjg"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_TUoqFm99EeaVpdzj7q6bjg" type="StateFigureCompartment">
+            <children xmi:id="_dFYyYG99EeaVpdzj7q6bjg" type="Region" element="_dFXkQG99EeaVpdzj7q6bjg">
+              <children xsi:type="notation:DecorationNode" xmi:id="_dFaAgG99EeaVpdzj7q6bjg" type="RegionName">
+                <styles xsi:type="notation:ShapeStyle" xmi:id="_dFaAgW99EeaVpdzj7q6bjg"/>
+                <layoutConstraint xsi:type="notation:Location" xmi:id="_dFaAgm99EeaVpdzj7q6bjg"/>
+              </children>
+              <children xsi:type="notation:Shape" xmi:id="_dFaAg299EeaVpdzj7q6bjg" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+                <children xmi:id="_eh5zsG99EeaVpdzj7q6bjg" type="State" element="_eh3XcG99EeaVpdzj7q6bjg">
+                  <children xsi:type="notation:DecorationNode" xmi:id="_eh6awG99EeaVpdzj7q6bjg" type="StateName">
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_eh6awW99EeaVpdzj7q6bjg"/>
+                    <layoutConstraint xsi:type="notation:Location" xmi:id="_eh6awm99EeaVpdzj7q6bjg"/>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_eh7o4G99EeaVpdzj7q6bjg" type="StateTextCompartment">
+                    <children xsi:type="notation:Shape" xmi:id="_eh7o4W99EeaVpdzj7q6bjg" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+                      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_eh7o4m99EeaVpdzj7q6bjg"/>
+                    </children>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_eh8P8G99EeaVpdzj7q6bjg" type="StateFigureCompartment"/>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_eh5zsW99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+                  <styles xsi:type="notation:FontStyle" xmi:id="_eh5zsm99EeaVpdzj7q6bjg"/>
+                  <styles xsi:type="notation:BooleanValueStyle" xmi:id="_eh8P8W99EeaVpdzj7q6bjg" name="isHorizontal" booleanValue="true"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_eh5zs299EeaVpdzj7q6bjg" x="13" y="92"/>
+                </children>
+                <children xmi:id="_fmmx8G99EeaVpdzj7q6bjg" type="Entry" element="_fmk8wG99EeaVpdzj7q6bjg">
+                  <children xmi:id="_fmnZAG99EeaVpdzj7q6bjg" type="BorderItemLabelContainer">
+                    <children xsi:type="notation:DecorationNode" xmi:id="_fmqcUG99EeaVpdzj7q6bjg" type="BorderItemLabel">
+                      <styles xsi:type="notation:ShapeStyle" xmi:id="_fmqcUW99EeaVpdzj7q6bjg"/>
+                      <layoutConstraint xsi:type="notation:Location" xmi:id="_fmqcUm99EeaVpdzj7q6bjg"/>
+                    </children>
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_fmnZAW99EeaVpdzj7q6bjg" fontName="Verdana" lineColor="4210752"/>
+                    <layoutConstraint xsi:type="notation:Bounds" xmi:id="_fmnZAm99EeaVpdzj7q6bjg"/>
+                  </children>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_fmmx8W99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+                  <styles xsi:type="notation:NamedStyle" xmi:id="_fmmx8m99EeaVpdzj7q6bjg" name="allowColors"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_fmmx8299EeaVpdzj7q6bjg" x="13" y="27"/>
+                </children>
+                <children xmi:id="_jFQqIG99EeaVpdzj7q6bjg" type="State" element="_jFNm0G99EeaVpdzj7q6bjg">
+                  <children xsi:type="notation:DecorationNode" xmi:id="_jFR4QG99EeaVpdzj7q6bjg" type="StateName">
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_jFR4QW99EeaVpdzj7q6bjg"/>
+                    <layoutConstraint xsi:type="notation:Location" xmi:id="_jFR4Qm99EeaVpdzj7q6bjg"/>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_jFR4Q299EeaVpdzj7q6bjg" type="StateTextCompartment">
+                    <children xsi:type="notation:Shape" xmi:id="_jFSfUG99EeaVpdzj7q6bjg" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+                      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_jFSfUW99EeaVpdzj7q6bjg"/>
+                    </children>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_jFSfUm99EeaVpdzj7q6bjg" type="StateFigureCompartment"/>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_jFQqIW99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+                  <styles xsi:type="notation:FontStyle" xmi:id="_jFQqIm99EeaVpdzj7q6bjg"/>
+                  <styles xsi:type="notation:BooleanValueStyle" xmi:id="_jFSfU299EeaVpdzj7q6bjg" name="isHorizontal" booleanValue="true"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_jFQqI299EeaVpdzj7q6bjg" x="159" y="87"/>
+                </children>
+                <layoutConstraint xsi:type="notation:Bounds" xmi:id="_dFaAhG99EeaVpdzj7q6bjg"/>
+              </children>
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_dFYyYW99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_dFYyYm99EeaVpdzj7q6bjg" x="220" y="425" width="400" height="326"/>
+            </children>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_TUoqF299EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_TUoqGG99EeaVpdzj7q6bjg"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_TUoqGW99EeaVpdzj7q6bjg" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_TUoqGm99EeaVpdzj7q6bjg" x="40" y="80" width="258" height="240"/>
+        </children>
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_TUoqG299EeaVpdzj7q6bjg"/>
+      </children>
+      <styles xsi:type="notation:ShapeStyle" xmi:id="_TUoqHG99EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_TUoqHW99EeaVpdzj7q6bjg" x="630" y="10" width="400" height="400"/>
+    </children>
+    <children xmi:id="_q_uJ0W9-EeaVpdzj7q6bjg" type="Region" element="_q_v_AG9-EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_q_uJ0m9-EeaVpdzj7q6bjg" type="RegionName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uJ029-EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_q_uJ1G9-EeaVpdzj7q6bjg"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_q_uJ1W9-EeaVpdzj7q6bjg" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+        <children xmi:id="_q_uJ1m9-EeaVpdzj7q6bjg" type="Entry" element="_q_v_AW9-EeaVpdzj7q6bjg">
+          <children xmi:id="_q_uJ129-EeaVpdzj7q6bjg" type="BorderItemLabelContainer">
+            <children xsi:type="notation:DecorationNode" xmi:id="_q_uJ2G9-EeaVpdzj7q6bjg" type="BorderItemLabel">
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uJ2W9-EeaVpdzj7q6bjg"/>
+              <layoutConstraint xsi:type="notation:Location" xmi:id="_q_uJ2m9-EeaVpdzj7q6bjg"/>
+            </children>
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uJ229-EeaVpdzj7q6bjg" fontName="Verdana" lineColor="4210752"/>
+            <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uJ3G9-EeaVpdzj7q6bjg"/>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uJ3W9-EeaVpdzj7q6bjg" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+          <styles xsi:type="notation:NamedStyle" xmi:id="_q_uJ3m9-EeaVpdzj7q6bjg" name="allowColors"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uJ329-EeaVpdzj7q6bjg" x="70" y="20" width="15" height="15"/>
+        </children>
+        <children xmi:id="_q_uJ4G9-EeaVpdzj7q6bjg" type="State" element="_q_wmEG9-EeaVpdzj7q6bjg">
+          <children xsi:type="notation:DecorationNode" xmi:id="_q_uJ4W9-EeaVpdzj7q6bjg" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uJ4m9-EeaVpdzj7q6bjg"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_q_uJ429-EeaVpdzj7q6bjg"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_q_uJ5G9-EeaVpdzj7q6bjg" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_q_uJ5W9-EeaVpdzj7q6bjg" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uJ5m9-EeaVpdzj7q6bjg"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_q_uJ529-EeaVpdzj7q6bjg" type="StateFigureCompartment">
+            <children xmi:id="_q_uJ6G9-EeaVpdzj7q6bjg" type="Region" element="_q_xNIG9-EeaVpdzj7q6bjg">
+              <children xsi:type="notation:DecorationNode" xmi:id="_q_uJ6W9-EeaVpdzj7q6bjg" type="RegionName">
+                <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uJ6m9-EeaVpdzj7q6bjg"/>
+                <layoutConstraint xsi:type="notation:Location" xmi:id="_q_uJ629-EeaVpdzj7q6bjg"/>
+              </children>
+              <children xsi:type="notation:Shape" xmi:id="_q_uJ7G9-EeaVpdzj7q6bjg" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+                <children xmi:id="_q_uJ7W9-EeaVpdzj7q6bjg" type="State" element="_q_xNIW9-EeaVpdzj7q6bjg">
+                  <children xsi:type="notation:DecorationNode" xmi:id="_q_uJ7m9-EeaVpdzj7q6bjg" type="StateName">
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uJ729-EeaVpdzj7q6bjg"/>
+                    <layoutConstraint xsi:type="notation:Location" xmi:id="_q_uJ8G9-EeaVpdzj7q6bjg"/>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_q_uJ8W9-EeaVpdzj7q6bjg" type="StateTextCompartment">
+                    <children xsi:type="notation:Shape" xmi:id="_q_uJ8m9-EeaVpdzj7q6bjg" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+                      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uJ829-EeaVpdzj7q6bjg"/>
+                    </children>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_q_uJ9G9-EeaVpdzj7q6bjg" type="StateFigureCompartment"/>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uJ9W9-EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+                  <styles xsi:type="notation:FontStyle" xmi:id="_q_uJ9m9-EeaVpdzj7q6bjg"/>
+                  <styles xsi:type="notation:BooleanValueStyle" xmi:id="_q_uJ929-EeaVpdzj7q6bjg" name="isHorizontal" booleanValue="true"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uJ-G9-EeaVpdzj7q6bjg" x="13" y="92"/>
+                </children>
+                <children xmi:id="_q_uJ-W9-EeaVpdzj7q6bjg" type="Entry" element="_q_ybQW9-EeaVpdzj7q6bjg">
+                  <children xmi:id="_q_uJ-m9-EeaVpdzj7q6bjg" type="BorderItemLabelContainer">
+                    <children xsi:type="notation:DecorationNode" xmi:id="_q_uw4G9-EeaVpdzj7q6bjg" type="BorderItemLabel">
+                      <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uw4W9-EeaVpdzj7q6bjg"/>
+                      <layoutConstraint xsi:type="notation:Location" xmi:id="_q_uw4m9-EeaVpdzj7q6bjg"/>
+                    </children>
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uw429-EeaVpdzj7q6bjg" fontName="Verdana" lineColor="4210752"/>
+                    <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw5G9-EeaVpdzj7q6bjg"/>
+                  </children>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uw5W9-EeaVpdzj7q6bjg" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+                  <styles xsi:type="notation:NamedStyle" xmi:id="_q_uw5m9-EeaVpdzj7q6bjg" name="allowColors"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw529-EeaVpdzj7q6bjg" x="13" y="27"/>
+                </children>
+                <children xmi:id="_q_uw6G9-EeaVpdzj7q6bjg" type="State" element="_q_ybQ29-EeaVpdzj7q6bjg">
+                  <children xsi:type="notation:DecorationNode" xmi:id="_q_uw6W9-EeaVpdzj7q6bjg" type="StateName">
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uw6m9-EeaVpdzj7q6bjg"/>
+                    <layoutConstraint xsi:type="notation:Location" xmi:id="_q_uw629-EeaVpdzj7q6bjg"/>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_q_uw7G9-EeaVpdzj7q6bjg" type="StateTextCompartment">
+                    <children xsi:type="notation:Shape" xmi:id="_q_uw7W9-EeaVpdzj7q6bjg" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+                      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw7m9-EeaVpdzj7q6bjg"/>
+                    </children>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_q_uw729-EeaVpdzj7q6bjg" type="StateFigureCompartment"/>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uw8G9-EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+                  <styles xsi:type="notation:FontStyle" xmi:id="_q_uw8W9-EeaVpdzj7q6bjg"/>
+                  <styles xsi:type="notation:BooleanValueStyle" xmi:id="_q_uw8m9-EeaVpdzj7q6bjg" name="isHorizontal" booleanValue="true"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw829-EeaVpdzj7q6bjg" x="159" y="87"/>
+                </children>
+                <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw9G9-EeaVpdzj7q6bjg"/>
+              </children>
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uw9W9-EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw9m9-EeaVpdzj7q6bjg" x="220" y="425" width="400" height="326"/>
+            </children>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uw929-EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_q_uw-G9-EeaVpdzj7q6bjg"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_q_uw-W9-EeaVpdzj7q6bjg" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw-m9-EeaVpdzj7q6bjg" x="40" y="80" width="258" height="240"/>
+        </children>
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw-29-EeaVpdzj7q6bjg"/>
+      </children>
+      <styles xsi:type="notation:ShapeStyle" xmi:id="_q_uw_G9-EeaVpdzj7q6bjg" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_q_uw_W9-EeaVpdzj7q6bjg" x="220" y="430" width="400" height="400"/>
+    </children>
+    <styles xsi:type="notation:DiagramStyle" xmi:id="_Pd96cW99EeaVpdzj7q6bjg"/>
+    <edges xmi:id="_PeuvcG99EeaVpdzj7q6bjg" type="Transition" element="_PethUW99EeaVpdzj7q6bjg" source="_Pep28G99EeaVpdzj7q6bjg" target="_PersIG99EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_PevWgW99EeaVpdzj7q6bjg" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_PevWgm99EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_PevWg299EeaVpdzj7q6bjg" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_PeuvcW99EeaVpdzj7q6bjg" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_PevWgG99EeaVpdzj7q6bjg" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_Peuvcm99EeaVpdzj7q6bjg" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+    </edges>
+    <edges xmi:id="_TUuwoG99EeaVpdzj7q6bjg" type="Transition" element="_TUs7cm99EeaVpdzj7q6bjg" source="_TUoqBW99EeaVpdzj7q6bjg" target="_TUoqD299EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_TUuwoW99EeaVpdzj7q6bjg" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_TUuwom99EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_TUuwo299EeaVpdzj7q6bjg" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_TUuwpG99EeaVpdzj7q6bjg" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_TUuwpW99EeaVpdzj7q6bjg" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_TUuwpm99EeaVpdzj7q6bjg" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+    </edges>
+    <edges xmi:id="_gk_FwG99EeaVpdzj7q6bjg" type="Transition" element="_gk8pgG99EeaVpdzj7q6bjg" source="_fmmx8G99EeaVpdzj7q6bjg" target="_eh5zsG99EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_gk_s0G99EeaVpdzj7q6bjg" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_gk_s0W99EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_gk_s0m99EeaVpdzj7q6bjg" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_gk_FwW99EeaVpdzj7q6bjg" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_gk_Fw299EeaVpdzj7q6bjg" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_gk_Fwm99EeaVpdzj7q6bjg" points="[3, 7, -44, -85]$[48, 88, 1, -4]"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_glElUG99EeaVpdzj7q6bjg" id="(0.13559322033898305,0.09433962264150944)"/>
+    </edges>
+    <edges xmi:id="_kKRxcG99EeaVpdzj7q6bjg" type="Transition" element="_kKPVMG99EeaVpdzj7q6bjg" source="_eh5zsG99EeaVpdzj7q6bjg" target="_jFQqIG99EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_kKSYgW99EeaVpdzj7q6bjg" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_kKSYgm99EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_kKSYg299EeaVpdzj7q6bjg" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_kKRxcW99EeaVpdzj7q6bjg" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_kKSYgG99EeaVpdzj7q6bjg" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_kKRxcm99EeaVpdzj7q6bjg" points="[4, 0, -98, -22]$[103, 47, 1, 25]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_kKXRAG99EeaVpdzj7q6bjg" id="(0.9322033898305084,0.39622641509433965)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_kKXRAW99EeaVpdzj7q6bjg" id="(0.13559322033898305,0.49056603773584906)"/>
+    </edges>
+    <edges xmi:id="_02yyEG99EeaVpdzj7q6bjg" type="Transition" element="_02w84G99EeaVpdzj7q6bjg" source="_PersIG99EeaVpdzj7q6bjg" target="_ze6ZIG99EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_02zZIG99EeaVpdzj7q6bjg" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_02zZIW99EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_02zZIm99EeaVpdzj7q6bjg" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_02yyEW99EeaVpdzj7q6bjg" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_02yyE299EeaVpdzj7q6bjg" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_02yyEm99EeaVpdzj7q6bjg" points="[8, -10, -160, 0]$[168, -10, 0, 0]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_0211YG99EeaVpdzj7q6bjg" id="(0.864406779661017,0.5849056603773585)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_022ccG99EeaVpdzj7q6bjg" id="(0.0,0.37735849056603776)"/>
+    </edges>
+    <edges xmi:id="_q_zpYG9-EeaVpdzj7q6bjg" type="Transition" element="_q_v_Am9-EeaVpdzj7q6bjg" source="_q_uJ1m9-EeaVpdzj7q6bjg" target="_q_uJ4G9-EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_q_zpYW9-EeaVpdzj7q6bjg" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_q_zpYm9-EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_q_zpY29-EeaVpdzj7q6bjg" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_q_zpZG9-EeaVpdzj7q6bjg" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_q_zpZW9-EeaVpdzj7q6bjg" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_q_zpZm9-EeaVpdzj7q6bjg" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+    </edges>
+    <edges xmi:id="_q_0QcG9-EeaVpdzj7q6bjg" type="Transition" element="_q_ybQm9-EeaVpdzj7q6bjg" source="_q_uJ-W9-EeaVpdzj7q6bjg" target="_q_uJ7W9-EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_q_0QcW9-EeaVpdzj7q6bjg" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_q_0Qcm9-EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_q_0Qc29-EeaVpdzj7q6bjg" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_q_0QdG9-EeaVpdzj7q6bjg" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_q_0QdW9-EeaVpdzj7q6bjg" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_q_0Qdm9-EeaVpdzj7q6bjg" points="[3, 7, -44, -85]$[48, 88, 1, -4]"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_q_0Qd29-EeaVpdzj7q6bjg" id="(0.13559322033898305,0.09433962264150944)"/>
+    </edges>
+    <edges xmi:id="_q_0QeG9-EeaVpdzj7q6bjg" type="Transition" element="_q_x0MG9-EeaVpdzj7q6bjg" source="_q_uJ7W9-EeaVpdzj7q6bjg" target="_q_uw6G9-EeaVpdzj7q6bjg">
+      <children xsi:type="notation:DecorationNode" xmi:id="_q_0QeW9-EeaVpdzj7q6bjg" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_q_0Qem9-EeaVpdzj7q6bjg"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_q_0Qe29-EeaVpdzj7q6bjg" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_q_0QfG9-EeaVpdzj7q6bjg" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_q_0QfW9-EeaVpdzj7q6bjg" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_q_0Qfm9-EeaVpdzj7q6bjg" points="[4, 0, -98, -22]$[103, 47, 1, 25]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_q_0Qf29-EeaVpdzj7q6bjg" id="(0.9322033898305084,0.39622641509433965)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_q_0QgG9-EeaVpdzj7q6bjg" id="(0.13559322033898305,0.49056603773584906)"/>
+    </edges>
+  </notation:Diagram>
+</xmi:XMI>