Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: b2ec3724b9eab117d7063854acc7eba7b8165697 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
[module acceptableEvents('http://www.eclipse.org/uml2/5.0.0/UML')/]
[import org::eclipse::papyrus::qompass::modellibs::core::acceleo::TransitionService /]
[import org::eclipse::papyrus::qompass::modellibs::core::acceleo::StateMachineUtil /]
[import org::eclipse::papyrus::qompass::designer::core::acceleo::UMLTool /]
[import org::eclipse::papyrus::qompass::designer::core::acceleo::EnumService /]
[import org::eclipse::papyrus::qompass::designer::vsl::ParseVSL /]

[comment produce a call event trigger label (TODO) /]

[comment
Pass the actual to which the port is bound. In case of a CallEvent, pass the implemented interface
(Not the class to which the state machine is bound)
/]
[template public cetrigger(operation: Operation) post(trim())]
	[boundPackageRef(operation.implementsInterface()).qualifiedName/]::ID_[name/]
	[comment declare dependency to OperationIDs enumeration /]
	[boundPackageRef(operation.implementsInterface()).declareDependencyToOperationIDs() /]
[/template]

[comment
Use service for global enumerations/]
[template public setrigger(trigger: Trigger) post(trim())]
	[literal('SignalEvents', 'SIG_' + trigger.event.oclAsType(SignalEvent).signal.name)/]
[/template]

[template public acceptableEvents(state: State)]

		// loop on state
		// execute action ...
		timeout = -1;	// no timeout by default
[for (transition : Transition | state.outgoing)]
	[if (transition.trigger->asSequence()->first().event.oclIsKindOf(TimeEvent))]
		// transition [name/] - trigger: TimeEvent, expression [transition.trigger->asSequence()->first().event.oclAsType(TimeEvent).when.expr.oclAsType(OpaqueExpression)._body->asSequence()->first()/].
		timeout = [getDurationFromVSL(trigger.event.oclAsType(TimeEvent).when.expr.oclAsType(OpaqueExpression)._body->asSequence()->first())/]/1000;
	[/if]
[/for]
		// upcoming support for nested state machines
		// timeout = setTimeoutInSubState (timeout);

		// get an event from the pool.
		event = ep->readEvent(timeout);
	
		// process event in sub-state
		// need variable for current sub-state, better array of variables? (graph, if we accept parallel states)
[if (state.region->size() > 0)]
	[comment sub states /]
[for (substate : State | state.region.subvertex->select(oclIsKindOf(State)))]
	[substate.acceptableSubEvents()/]
[/for]
[/if]
		// processEventInSubState (event);

[for (transition : Transition | state.outgoing)]
	[comment big restriction: will only analyse first of possibly multiple triggers/]
	[let trigger : Trigger = transition.trigger->asSequence()->first()]
	[if (trigger.event.oclIsKindOf(TimeEvent))]
		// transition [transition.name/] - trigger: TimeEvent (there should be at most one outgoing timed transition per state).
		if (event.operationID == core::ContainerServices::EventPool::ID_TIMEOUT) {
			newState = STATE_[transition.target.name/];
[if not (transition.effect = null)]			executor->[state.containingStateMachine().name/]_[transition.name/]_[transition.effect.name/]();
[/if]
		}		
	[/if]
	[if (trigger.event.oclIsKindOf(CallEvent))] 
		// transition [name/] - trigger: CallEvent ([trigger.event.name/]), operation [trigger.event.oclAsType(CallEvent).operation.name/]
		if (event.operationID == [cetrigger(trigger.event.oclAsType(CallEvent).operation)/]) {
			newState = STATE_[transition.target.name/];
[if not (transition.effect = null)]			executor->[state.containingStateMachine().name/]_[transition.name/]_[transition.effect.name/]();
[/if]
		} 
	[/if]
	[if (trigger.event.oclIsKindOf(SignalEvent))] 
		[let signalEvent : SignalEvent = trigger.event.oclAsType(SignalEvent)]
		// transition [name/] - trigger: SignalEvent ([signalEvent.name/]), signal [signalEvent.signal.name/]
		if (event.operationID == [setrigger(trigger)/]) {
			newState = STATE_[transition.target.name/];
[if not (transition.effect = null)]			[if signalEvent.signal.attribute->size() > 0]void* data = &event.params;[/if] 
			executor->[state.containingStateMachine().name/]_[transition.name/]_[transition.effect.name/]([if signalEvent.signal.attribute->size() > 0]data[/if]);

[/if]
			// ok = EvQUEUE ;
		}
		[/let]
	[/if]
	[/let]
[/for]
		if (newState != m_currentState) {
			m_currentState = newState;
		}
[/template]

[template public acceptableSubEvents(state: State)]
// handle substates
[for (transition : Transition | state.outgoing)]
	[comment big restriction: will only analyse first of possibly multiple triggers/]
	[if (transition.trigger->asSequence()->first().event.oclIsKindOf(TimeEvent))]
		// transition [transition.name/] - trigger: TimeEvent (there should be at most one outgoing timed transition per state).
		if (event.operationID == core::ContainerServices::EventPool::ID_TIMEOUT) {
			newSubState = STATE_[transition.target.name/];
[if not (transition.effect = null)]			executor->[state.containingStateMachine().name/]_[transition.name/]_[transition.effect.name/]();
[/if]
		}		
	[/if]
	[if (transition.trigger->asSequence()->first().event.oclIsKindOf(CallEvent))] 
		// transition [name/] - trigger: CallEvent, operation [transition.trigger.event.oclAsType(CallEvent).operation.name/]
		if (event.operationID == [cetrigger(transition.trigger->asSequence()->first().event.oclAsType(CallEvent).operation)/]) {
			newSubState = STATE_[transition.target.name/];
[if not (transition.effect = null)]			executor->[state.containingStateMachine().name/]_[transition.name/]_[transition.effect.name/]();
[/if]
		} 
	[/if]
	[if (transition.trigger->asSequence()->first().event.oclIsKindOf(SignalEvent))] 
		// transition [name/] - trigger: SignalEvent, signal [transition.trigger.event.oclAsType(SignalEvent).signal.name/]
		if (event.operationID == SIG_[transition.trigger.event.oclAsType(SignalEvent).signal.name/]) {
			newSubState = STATE_[transition.target.name/]) ;
[if not (transition.effect = null)]			executor->[state.containingStateMachine().name/]_[transition.name/]_[transition.effect.name/]();
[/if]
			// ok = EvQUEUE ;
		}
	[/if]
[/for]
[/template]

Back to the top