Forráskód Böngészése

fixed bug #1014 - "Initial Entry Action (hierarchical states)"

terfloth@itemis.de 11 éve
szülő
commit
03ad538d4d

+ 12 - 9
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/ReactionBuilder.xtend

@@ -32,6 +32,7 @@ class ReactionBuilder {
 	@Inject extension SgraphExtensions sgraph
 	@Inject extension StatechartExtensions sct
 	@Inject extension TraceExtensions trace
+	@Inject extension BehaviorMapping behaviorMapping
 	
 	def defineStatechartReaction(ExecutionFlow flow, Statechart sc) {
 		val sequence = sexec.factory.createSequence
@@ -210,14 +211,16 @@ class ReactionBuilder {
 		//Reuse already created react sequence from defineStateEnterSequence(Entry) 
 		val seq = execEntry.reactSequence
 		val target = e.target.create
+		val targetEnterSequence = if (target != null && e.outgoingTransitions.size > 0) { e.outgoingTransitions.mapToStateConfigurationEnterSequence } else null
+			
 		
 		if ( trace.addTraceSteps ) seq.steps.add(0,execEntry.newTraceNodeExecuted)
 		
 		if (e.kind == EntryKind::INITIAL) {
-			if (target != null && target.enterSequences.defaultSequence != null) {
-				if (trace.addTraceSteps) seq.steps += e.outgoingTransitions.get(0).create.newTraceReactionFired
-				seq.steps += target.enterSequences.defaultSequence.newCall
+			if (targetEnterSequence != null) {
+				seq.steps += targetEnterSequence
 			}
+			
 		} else if (e.kind == EntryKind::SHALLOW_HISTORY) {
 			val entryStep = sexec.factory.createHistoryEntry
 			entryStep.name = "HistoryEntry"
@@ -226,10 +229,10 @@ class ReactionBuilder {
 			entryStep.region = (e.eContainer as Region).create
 			
 			//Initial step, if no history is known
-			if (target != null && target.enterSequences.defaultSequence != null) {
-				if (trace.addTraceSteps) seq.steps += e.outgoingTransitions.get(0).create.newTraceReactionFired
-				entryStep.initialStep = target.enterSequences.defaultSequence.newCall
+			if (targetEnterSequence != null) {
+				entryStep.initialStep = targetEnterSequence
 			}
+			
 			entryStep.historyStep = (e.eContainer as Region).create.shallowEnterSequence.newCall
 			
 			seq.steps += entryStep
@@ -241,10 +244,10 @@ class ReactionBuilder {
 			entryStep.deep = true
 			
 			//Initial step, if no history is known
-			if (target != null && target.enterSequences.defaultSequence != null) {
-				if (trace.addTraceSteps) seq.steps += e.outgoingTransitions.get(0).create.newTraceReactionFired
-				entryStep.initialStep = target.enterSequences.defaultSequence.newCall
+			if (targetEnterSequence != null) {
+				entryStep.initialStep = targetEnterSequence
 			}
+			
 			entryStep.historyStep =  (e.eContainer as Region).create.deepEnterSequence.newCall
 
 			seq.steps += entryStep

+ 9 - 1
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/SequenceBuilder.xtend

@@ -199,7 +199,15 @@ class SequenceBuilder {
 		state.regions.forEach( r | r.defineScopeEnterSequences )
 		
 		// get all entry point names used by incoming transitions
-		val entryPointNames = state.incomingTransitions.map( t | t.entryPointName ).toSet.toList.sortInplace
+		val entryPointNames = state.incomingTransitions.map( t | t.entryPointName ).toSet.toList
+		
+		// also include implicit entries by histories
+		if (state.parentRegion.requireHistory) {
+			if (!entryPointNames.contains('default')) entryPointNames.add('default')
+		}   
+		
+		// sort entry points by name ...
+		entryPointNames.sortInplace
 		
 		// create an entry sequence for each entry point
 		for ( epName : entryPointNames ) {

+ 4 - 2
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/SgraphExtensions.xtend

@@ -81,12 +81,14 @@ class SgraphExtensions {
 	 * TODO: validation of preconditions for entry targets e.g every region needs an entry with appropriate target
 	 */
 	def target(Entry entry) {
+		var State target = null
 		if ( entry?.outgoingTransitions != null) {
 			if (entry.outgoingTransitions.size > 0) {
-				val target =entry.outgoingTransitions.get(0).target
-				if (target instanceof State ) target as State	
+				val obj =entry.outgoingTransitions.get(0).target
+				if (obj instanceof State ) target = obj as State	
 			}
 		}
+		return target
 	}
 	
 	

+ 26 - 1
plugins/org.yakindu.sct.model.sgraph/src/org/yakindu/sct/model/sgraph/validation/SGraphJavaValidator.java

@@ -60,6 +60,7 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 	public static final String ISSUE_ENTRY_WITH_MULTIPLE_OUT_TRANS = "Entries must not have more than one outgoing transition";
 	public static final String ISSUE_ENTRY_WITH_TRIGGER = "Outgoing Transitions from Entries can not have a Trigger or Guard.";
 	public static final String ISSUE_CHOICE_WITHOUT_OUTGOING_TRANSITION = "A choice must have at least one outgoing transition.";
+	public static final String ISSUE_REGION_CANT_BE_ENTERED_USING_SHALLOW_HISTORY = "The region can't be entered using the shallow history. Add an entry node.";
 	public static final String ISSUE_SUBMACHINE_UNRESOLVABLE = "Referenced Substatemachine '%s'does not exist!";
 	public static final String ISSUE_SYNCHRONIZATION_TARGET_STATES_NOT_ORTHOGONAL = "The target states of a synchronization must be orthogonal!";
 	public static final String ISSUE_SYNCHRONIZATION_TARGET_STATES_NOT_WITHIN_SAME_PARENTSTATE = "The target states of a synchronization have to be contained in the same parent state within different regions!";
@@ -183,6 +184,29 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 		}
 	}
 
+	
+	@Check(CheckType.FAST)
+	public void regionCantBeEnteredUsingShallowHistory(org.yakindu.sct.model.sgraph.State s) {
+		
+		for (Vertex v : s.getParentRegion().getVertices()) {
+			if (v instanceof Entry && ((Entry)v).getKind() == EntryKind.SHALLOW_HISTORY) {
+				for (Region r : s.getRegions() ) {
+					boolean entryExists = false;
+					for (Vertex childVertex : r.getVertices() ) {
+						if ( childVertex instanceof Entry ) {
+							entryExists = true;
+						}
+					}
+					if (!entryExists ) {
+						error(ISSUE_REGION_CANT_BE_ENTERED_USING_SHALLOW_HISTORY, r, null, -1);
+					}
+				}
+				break;
+			}
+		}
+	}
+
+	
 	@Check(CheckType.FAST)
 	public void orthogonalStates(Synchronization fork) {
 		// check target states
@@ -191,7 +215,8 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 		orthogonalStates(fork, false);
 	}
 
-
+	
+	
 	private void orthogonalStates(Synchronization fork, boolean searchTarget) {
 		List<Transition> transitions = searchTarget ? fork.getOutgoingTransitions() : fork.getIncomingTransitions();
 		if (transitions.size() > 1) {