blob: b44e4b9b2944fbe716bc65e8b0ddfe4d285a684f [file] [log] [blame]
package org.eclipse.papyrus.designer.languages.c.codegen.lib
import java.util.ArrayList
import java.util.List
import org.eclipse.papyrus.designer.languages.c.codegen.preferences.CCodeGenConstants
import org.eclipse.papyrus.designer.languages.common.base.GenUtils
import org.eclipse.uml2.uml.CallEvent
import org.eclipse.uml2.uml.Class
import org.eclipse.uml2.uml.Event
import org.eclipse.uml2.uml.OpaqueBehavior
import org.eclipse.uml2.uml.OpaqueExpression
import org.eclipse.uml2.uml.Region
import org.eclipse.uml2.uml.State
import org.eclipse.uml2.uml.StateMachine
import org.eclipse.uml2.uml.Transition
import org.eclipse.uml2.uml.Vertex
import org.eclipse.uml2.uml.FinalState
import java.util.regex.Pattern
class stateMachineScript {
static List<Transition> transitions = new ArrayList
public static Region region
public List<State> states = new ArrayList
List<Vertex> vertexes = new ArrayList
public static String ACTIVE_ROOT_STATE_ID = "activeStateID"
def static genProcessCompletionEventMethodBody(Class clazz) {
region = clazz.ownedBehaviors.filter(StateMachine).head.regions.head;
transitions.addAll(region.transitions.filter[it.source !== null && it.target !== null])
val NonTriggeredTrans = new ArrayList<Transition>
transitions.forEach [
if (it.source instanceof State && ! (it.target instanceof FinalState) && (it.triggers.map[it.event].size == 0)) {
NonTriggeredTrans.add(it)
}
]
val sources = NonTriggeredTrans.map[it.source].filter(State).toSet;
val setTransitions= NonTriggeredTrans.toSet;
var body = '''
«IF NonTriggeredTrans.size > 0»
switch(self->«ACTIVE_ROOT_STATE_ID») {
«FOR state:sources»
case «state.name»:
«FOR t:setTransitions»
«IF t.source==state»
«generateTransitionCode(t.source as State, t)»
«ENDIF»
«ENDFOR»
{}
break;
«ENDFOR»
default:
//do nothing
break;
}
«ENDIF»
'''
return body
}
def static genProcessMethodBody(Event callevent, Class clazz) {
region = clazz.ownedBehaviors.filter(StateMachine).head.regions.head;
transitions.addAll(region.transitions.filter[it.source !== null && it.target !== null])
val TriggeredTrans = new ArrayList<Transition>
transitions.forEach [
if (it.source instanceof State && !(it.triggers.map[it.event].size == 0)) {
var events = it.triggers.map[it.event].toList;
if (events.contains(callevent)) {
if (!TriggeredTrans.contains(it)) {
TriggeredTrans.add(it)
}
}
}
]
val sources = TriggeredTrans.map[it.source].filter(State).toSet;
var body = '''
«IF TriggeredTrans.size > 0»
switch(self->«ACTIVE_ROOT_STATE_ID») {
«FOR state:sources»
case «state.name»:
«FOR t:TriggeredTrans »
«IF t.source==state»
«generateTransitionCode(t.source as State, t)»
«ENDIF»
«ENDFOR»
{}
break;
«ENDFOR»
default:
//do nothing
break;
}
«ENDIF»
'''
return body
}
def static String generateTransitionCode(State s, Transition t) {
var ret = ''''''
val cGuard = getGuard(t)
val acslGuard = acslScript.getGuard(t)
if (t.target instanceof State) {
ret = '''
/* transition guard */
«IF !acslGuard.empty»«acslGuard»«ENDIF»
if («IF !cGuard.empty»«cGuard»«ELSE»1«ENDIF») {
/* exit Transition source */
if (self->states[«t.source.getName()»].exit != NULL) {
self->states[«t.source.getName()»].exit();
}
/* transition effect*/
«t.getTransitionEffect»
/* update current state */
self->«ACTIVE_ROOT_STATE_ID» = «t.target.getName()» ;
/* entry of the new state */
if (self->states[«t.target.getName()»].entry != NULL) {
self->states[«t.target.getName()»].entry();
}
/* doActivity of the new state */
if (self->states[«t.target.getName()»].doActivity != NULL) {
self->states[«t.target.getName()»].doActivity();
}
/* always call process completion event to handle completion transition */
ProcessCompletionEvent(self);
} else'''
}
return ret
}
def static String getTransitionEffect(Transition t) {
if (t.effect !== null && t.effect instanceof OpaqueBehavior) {
return (t.effect as OpaqueBehavior).bodies.head
}
return ''''''
}
def static getGuard(Transition t) {
if (t.guard !== null && t.guard.specification instanceof OpaqueExpression) {
val opaqueExpression = t.guard.specification as OpaqueExpression;
if (opaqueExpression.languages.size === opaqueExpression.bodies.size) {
for (var i = 0; i < opaqueExpression.languages.size; i++) {
val language = opaqueExpression.languages.get(i)
val matcher = CCodeGenConstants.supportedLanguages.matcher(language);
if (matcher.matches()) {
return GenUtils.cleanCR(opaqueExpression.bodies.get(i));
}
}
}
}
return ""
}
def static getGuard(Transition t, Pattern selectedLanguages) {
if (t.guard !== null && t.guard.specification instanceof OpaqueExpression) {
val opaqueExpression = t.guard.specification as OpaqueExpression;
if (opaqueExpression.languages.size === opaqueExpression.bodies.size) {
for (var i = 0; i < opaqueExpression.languages.size; i++) {
val language = opaqueExpression.languages.get(i)
val matcher = selectedLanguages.matcher(language);
if (matcher.matches()) {
return GenUtils.cleanCR(opaqueExpression.bodies.get(i));
}
}
}
}
return ""
}
}