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 "" | |
} | |
} |