From 91a4cc7b16af391611fe5c6489b6f2446d939cb9 Mon Sep 17 00:00:00 2001 From: Sophie Coudert <sophie.coudert@telecom-paris.fr> Date: Wed, 26 Jun 2024 17:00:14 +0200 Subject: [PATCH] save. Avatar2SysML commented until line 1126, next: clean_guard --- .../tosysmlv2/Avatar2SysML.java | 468 +++++++++++------- 1 file changed, 278 insertions(+), 190 deletions(-) diff --git a/src/main/java/avatartranslator/tosysmlv2/Avatar2SysML.java b/src/main/java/avatartranslator/tosysmlv2/Avatar2SysML.java index 562ac1b219..aeb17fbc03 100644 --- a/src/main/java/avatartranslator/tosysmlv2/Avatar2SysML.java +++ b/src/main/java/avatartranslator/tosysmlv2/Avatar2SysML.java @@ -45,6 +45,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.ArrayList; +import java.util.function.BiConsumer; /** @@ -59,12 +60,10 @@ public class Avatar2SysML { private AvatarSpecification avspec; /** the buffer in which theSysML Model is written (returned at the end of the generation process) */ private StringBuffer avsysml; - /** signals concerned by AvatarQueryOnSignal */ + /** signals concerned by AvatarQueryOnSignal (collected at beginning because require some specific handling)*/ private HashSet<AvatarSignal> fifoSet = new HashSet<AvatarSignal>(); + /** infos about methods and signals collected while generation declarations and used while generating state machines */ private HashMap<AvatarMethod, MethodInfo> methodMap = new HashMap<AvatarMethod, MethodInfo>(); - private HashMap<AvatarStateMachineElement, StateInfo> stateMap = new HashMap<AvatarStateMachineElement, StateInfo>(); - private ArrayList<AvatarStateMachineElement> stateList = new ArrayList<AvatarStateMachineElement>(); - private ArrayList<AvatarAttribute> timerList = new ArrayList<AvatarAttribute>(); /** path from top level to the block (block sequence) being currently handled */ private ArrayList<String> blockChain = new ArrayList<String>(); /** SysML code to make inner blocks visible at top level. Contains one declaration per inner block */ @@ -93,8 +92,6 @@ public class Avatar2SysML { public StringBuffer avatar2SysML() { fifoSet.clear(); methodMap.clear(); - stateMap.clear(); - stateList.clear(); blockChain.clear(); indentation = ""; blockLinks = new StringBuffer(indentStep + "// Block Shortcut Links $$$$$$$$$$$$\n"); @@ -116,7 +113,7 @@ public class Avatar2SysML { /** infos collected while generating declarations of methods and signals, to be used later. * - * (for example when handling ActionsOnSignal) */ + * Used when generating state machine description, for example when handling ActionsOnSignal. */ static private class MethodInfo { private String name; // method name private String msgtype; // null for methods that are not signals @@ -319,7 +316,7 @@ public class Avatar2SysML { * <li> in/out Messages (structures) declarations, linking them to channels. This providing signals with profiles </li> * </ul> */ - void communications2SysML(){ + private void communications2SysML(){ int nbfiforelNumber = 0; int bfiforelNumber = 0; int syncrelNumber = 0; @@ -519,7 +516,7 @@ public class Avatar2SysML { /** generates SysML declarations for block methods. * To be called while generating block declarations. Directly put generated text in avsysml. */ - void method2SysML(AvatarMethod am){ + private void method2SysML(AvatarMethod am){ MethodInfo methodInfo; // to collect info @@ -601,15 +598,16 @@ public class Avatar2SysML { * To be called while generating block declarations. Directly put generated text in avsysml. Signals used in AvatarQueryOnSignal elements must * be typed as fifos (other ones are not constrained). Thus, fifoSet must have been computed before calling this method. */ - void signal2SysML(AvatarSignal as){ + private void signal2SysML(AvatarSignal as){ avsysml.append(indentation + "part " + methodMap.get(as).getName() + " : " + (fifoSet.contains(as) ? "'#Fifo'" : "'#Channel'") + ";\n"); } - /** generates SysML declarations for blocks and declaration to directly access inner blocks through their name (not their full path) */ - void block2SysML(AvatarBlock block){ + /** generates SysML declarations for a blocks and direct access to inner blocks through their name (not their full path) */ + private void block2SysML(AvatarBlock block){ String blockSYSMLname = blockSysMLname(block.getName()); - timerList.clear(); // to memorize timers while iterating on attributes (delayed declarations) + // to memorize timers while iterating on attributes (delayed declarations) + ArrayList<AvatarAttribute> timerList = new ArrayList<AvatarAttribute>(); chainBlock(blockSYSMLname); blocklink(); // to directly access inner blocks through their (short) name @@ -723,16 +721,24 @@ public class Avatar2SysML { unchainBlock(); } - // handling all blocks - void blocks2SysML(){ + /** generates SysML declarations for all blocks: iterate on specification block list */ + private void blocks2SysML(){ avsysml.append("\n" + indentation + "// BLOCKS $$$$$$$$$$$$$$$$$$$$$$$$\n"); for(AvatarBlock block: avspec.getListOfBlocks()) if (block.getFather() == null) block2SysML(block); } - Boolean stopState; - void statemachine2SysML(AvatarStateMachine asm) { - stateList.clear(); - // associate names to future SysML states + + /** generates state information for each state machine element of the specification and technically + * added states (before some communication elements). Put this information in a map which is returned. + */ + private HashMap<AvatarStateMachineElement, StateInfo> computeStateInfo(AvatarStateMachine asm) { + + // the map to fill and return + HashMap<AvatarStateMachineElement, StateInfo> stateMap = new HashMap<AvatarStateMachineElement, StateInfo>(); + + // associate names to future SysML states......................... + + // number to identify states in an unambigous way int randomNumber = 0; int countNumber = 0; int sendNumber = 0; @@ -740,301 +746,383 @@ public class Avatar2SysML { int setNumber = 0; int resetNumber = 0; int expireNumber = 0; + + // produces and memorize stateinfo structure (couple name, prename) for all state machine element for (AvatarStateMachineElement asme : asm.getListOfElements()) { StateInfo stateinfo; - if (asme instanceof AvatarStartState) + // states without communication hav just a name. + if (asme instanceof AvatarStartState) stateinfo = new StateInfo(startStateSysMLname()); else if (asme instanceof AvatarStopState) stateinfo = new StateInfo(stopStateSysMLname()); else if (asme instanceof AvatarState) stateinfo = new StateInfo(standardStateSysMLname(asme.getName())); + else if (asme instanceof AvatarQueryOnSignal) + stateinfo = new StateInfo(countStateSysMLname(((AvatarQueryOnSignal) asme).getSignal().getName(), countNumber++)); + else if (asme instanceof AvatarRandom) + stateinfo = new StateInfo(randomStateSysMLname(randomNumber++)); + // next cases rely on communication and thus, are subject to the introduction of an additional "preceding" state. else if (asme instanceof AvatarActionOnSignal) { - if(((AvatarActionOnSignal)asme).isSending()) + if (((AvatarActionOnSignal) asme).isSending()) stateinfo = new StateInfo( - sendStateSysMLname(((AvatarActionOnSignal)asme).getSignal().getName(), sendNumber), - presendStateSysMLname(((AvatarActionOnSignal)asme).getSignal().getName(), sendNumber++)); + sendStateSysMLname(((AvatarActionOnSignal) asme).getSignal().getName(), sendNumber), + presendStateSysMLname(((AvatarActionOnSignal) asme).getSignal().getName(), sendNumber++)); else - stateinfo = new StateInfo(receiveStateSysMLname(((AvatarActionOnSignal)asme).getSignal().getName(), receiveNumber), - prereceiveStateSysMLname(((AvatarActionOnSignal)asme).getSignal().getName(), receiveNumber++)); - } - else if (asme instanceof AvatarSetTimer) { - stateinfo = new StateInfo(setTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(),setNumber), + stateinfo = new StateInfo(receiveStateSysMLname(((AvatarActionOnSignal) asme).getSignal().getName(), receiveNumber), + prereceiveStateSysMLname(((AvatarActionOnSignal) asme).getSignal().getName(), receiveNumber++)); + } else if (asme instanceof AvatarSetTimer) { + stateinfo = new StateInfo(setTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(), setNumber), presetTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(), setNumber++)); - } - else if (asme instanceof AvatarResetTimer) { - stateinfo = new StateInfo(resetTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(),resetNumber), + } else if (asme instanceof AvatarResetTimer) { + stateinfo = new StateInfo(resetTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(), resetNumber), preresetTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(), resetNumber++)); - } - else if (asme instanceof AvatarExpireTimer) { - stateinfo = new StateInfo(expireTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(),expireNumber), + } else if (asme instanceof AvatarExpireTimer) { + stateinfo = new StateInfo(expireTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(), expireNumber), preexpireTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(), expireNumber++)); - } - else if (asme instanceof AvatarQueryOnSignal) - stateinfo = new StateInfo(countStateSysMLname(((AvatarQueryOnSignal)asme).getSignal().getName(), countNumber++)); - else if (asme instanceof AvatarRandom) - stateinfo = new StateInfo(randomStateSysMLname(randomNumber++)); - else continue; - stateList.add(asme); + } else continue; // TODO ? curious states "AvatarEmpty" not handled stateMap.put(asme, stateinfo); } + return stateMap; + } + + /** generates SysML description of state machine */ + private void statemachine2SysML(AvatarStateMachine asm) { + HashMap<AvatarStateMachineElement, StateInfo> stateMap = computeStateInfo(asm); + + // put state-machine header to avsysml............................. avsysml.append(indentation + "exhibit state '@statemachine' : '#AvatarStateMachine' {\n"); indent(1); - // generate SysML states with associated transitions - stopState = false; - for (AvatarStateMachineElement asme : stateList) state2SysML(asme); + + // put SysML states descriptions with associated transition descriptions......... + stateMap.forEach(new State2SysML(stateMap)); + unindent(1); avsysml.append(indentation + "}\n"); } + + /** buffer to build SysML declarations of outgoing transitions from one state(filled by method transitionsAndRequests) */ StringBuffer sysMLtransitions = new StringBuffer(); + /** buffer to build in-a-state requests associated to the outgoing transitions of this state (filled by method transitionsAndRequests) */ StringBuffer sysMLrequests = new StringBuffer(); + /** communication (and timer) states that require an added state before (as they have incomming transitions with action, from the currently + * handled state) (filled by method transitionsAndRequests) */ List<AvatarStateMachineElement> requirePreCom = new ArrayList<AvatarStateMachineElement>(); - void state2SysML(AvatarStateMachineElement asme){ - indent(1); - transitionsAndRequests(stateMap.get(asme).getName(), asme.getNexts(), ((asme instanceof AvatarState) ? "'@pool'" : "'@request'")); - unindent(1); - - String requests = sysMLrequests.toString(); + /** to iterate on the state machine elements of one block. An iteration puts a state declaration in avsysml, followed by the declarations of + * its outgoing transitions. If the needed technically added pre-communication are detected while handling these transitions. The declarations + * of these added states are added after the transition declarations, followed by their own single outgoing transition. + */ + private class State2SysML implements BiConsumer<AvatarStateMachineElement, StateInfo> { + /** provides all states with name information */ + HashMap<AvatarStateMachineElement, StateInfo> stateMap; - // State Description, depending on state type + /** false untill stopState has been encountered (as it can be encountered several times but generated only once) */ + Boolean stopStateDone; - if(asme instanceof AvatarState){ - avsysml.append("\n" + indentation + "state " + stateMap.get(asme).getName() + " : '#AvatarStandardState'"); - if (requests.equals("")) - avsysml.append(";\n"); - else - avsysml.append(" = '#AvatarStandardState'(\n" + requests + "\n" + indentation + ");\n"); - } else + public State2SysML(HashMap<AvatarStateMachineElement, StateInfo> _stateMap) { + stateMap = _stateMap; + stopStateDone = false; + } - if(asme instanceof AvatarRandom){ - avsysml.append("\n" + indentation + "state " + stateMap.get(asme).getName() + " : '#AvatarRandomState' = '#AvatarRandomState'(\n"); - if (!requests.equals("")) avsysml.append(requests + ",\n"); - indent(1); - avsysml.append(indentation + "'@state_action' = '#Assignment'(\n"); + /** puts a state declaration in avsysml, followed by the declarations of + * its outgoing transitions. If the needed technically added pre-communication are detected while handling these transitions. The declarations + * of these added states are added after the transition declarations, followed by their own single outgoing transition. + */ + public void accept(AvatarStateMachineElement asme, StateInfo info) { + // compute transition declarations and request descriptions for the outgoing transitions of the state + // identify states that require an added pre-communication state indent(1); - avsysml.append(indentation + "'@target' = " + attributeSysMLname(((AvatarRandom)asme).getVariable()) + ",\n"); - avsysml.append(indentation + "'@value' = '#bound_random'(" + - expr2SysML(((AvatarRandom)asme).getMinValue().replaceAll("__",".")) + ", " + - expr2SysML(((AvatarRandom)asme).getMaxValue().replaceAll("__",".")) +")\n"); - unindent(1); - avsysml.append(indentation + ")\n"); + transitionsAndRequests(info.getName(), asme.getNexts(), ((asme instanceof AvatarState) ? "'@pool'" : "'@request'"), stateMap); unindent(1); - avsysml.append(indentation + ");\n"); - } else - if(asme instanceof AvatarQueryOnSignal){ - avsysml.append("\n" + indentation + "state " + stateMap.get(asme).getName() + " : '#AvatarCountState' = '#AvatarCountState'(\n"); - if (!requests.equals("")) avsysml.append(requests + ",\n"); - indent(1); - avsysml.append(indentation + "'@state_action' = '#Assignment'(\n"); - indent(1); - avsysml.append(indentation + "'@target' = " + attributeSysMLname(((AvatarQueryOnSignal)asme).getAttribute().getName()) + ",\n"); - avsysml.append(indentation + "'@value' = " + methodMap.get(((AvatarQueryOnSignal)asme).getSignal()).getName() + ".'@amount'()\n"); - unindent(1); - avsysml.append(indentation + ")\n"); - unindent(1); - avsysml.append(indentation + ");\n"); - } else + String requests = sysMLrequests.toString(); // to put after state declaration - if(asme instanceof AvatarActionOnSignal){ - if(((AvatarActionOnSignal)asme).isSending()) { - avsysml.append("\n" + indentation + "state " + stateMap.get(asme).getName() + " : '#AvatarSendState'"); - if (requests.equals("")) - avsysml.append(";\n"); - else - avsysml.append(" = '#AvatarSendState'(\n" + requests + "\n" + indentation + ");\n"); - } else { - avsysml.append("\n" + indentation + "state " + stateMap.get(asme).getName() + " : '#AvatarReceiveState'"); + // put state Descriptions ................................ + // depending on state type + + if(asme instanceof AvatarState){ + avsysml.append("\n" + indentation + "state " + info.getName() + " : '#AvatarStandardState'"); if (requests.equals("")) avsysml.append(";\n"); else - avsysml.append(" = '#AvatarReceiveState'(\n" + requests + "\n" + indentation + ");\n"); - } - } else + avsysml.append(" = '#AvatarStandardState'(\n" + requests + "\n" + indentation + ");\n"); + } else - if(asme instanceof AvatarStartState){ - avsysml.append("\n" + indentation + "entry action " + stateMap.get(asme).getName() + " :'#AvatarStartState'"); - if (requests.equals("")) - avsysml.append(";\n"); - else - avsysml.append(" = '#AvatarStartState'(\n" + requests + "\n" + indentation + ");\n"); - } else - - if(asme instanceof AvatarStopState){ - if(! stopState) - avsysml.append("\n" + indentation + "exit action " + stateMap.get(asme).getName() + " :'#AvatarStopState';\n"); - stopState = true; - } else - - if(asme instanceof AvatarSetTimer){ - avsysml.append("\n" + indentation + "state " + stateMap.get(asme).getName() + " : '#AvatarSetTimerState'"); - if (requests.equals("")) - avsysml.append(";\n"); - else - avsysml.append(" = '#AvatarSetTimerState'(\n" + requests + "\n" + indentation + ");\n"); - } else + if(asme instanceof AvatarRandom){ // specific: assign a random value to a variable + avsysml.append("\n" + indentation + "state " + info.getName() + " : '#AvatarRandomState' = '#AvatarRandomState'(\n"); + if (!requests.equals("")) avsysml.append(requests + ",\n"); // put request description (none means default request) + indent(1); + avsysml.append(indentation + "'@state_action' = '#Assignment'(\n"); + indent(1); + // the variable to be assigned + avsysml.append(indentation + "'@target' = " + attributeSysMLname(((AvatarRandom)asme).getVariable()) + ",\n"); + // the random value to assign + avsysml.append(indentation + "'@value' = '#bound_random'(" + + expr2SysML(((AvatarRandom)asme).getMinValue().replaceAll("__",".")) + ", " + + expr2SysML(((AvatarRandom)asme).getMaxValue().replaceAll("__",".")) +")\n"); + unindent(1); + avsysml.append(indentation + ")\n"); + unindent(1); + avsysml.append(indentation + ");\n"); + } else - if(asme instanceof AvatarResetTimer){ - avsysml.append("\n" + indentation + "state " + stateMap.get(asme).getName() + " : '#AvatarResetTimerState'"); - if (requests.equals("")) - avsysml.append(";\n"); - else - avsysml.append(" = '#AvatarResetTimerState'(\n" + requests + "\n" + indentation + ");\n"); - } else + if(asme instanceof AvatarQueryOnSignal){ // specific: assign the content size of a signal to a variable + avsysml.append("\n" + indentation + "state " + info.getName() + " : '#AvatarCountState' = '#AvatarCountState'(\n"); + if (!requests.equals("")) avsysml.append(requests + ",\n"); // put request description (none means default request) + indent(1); + avsysml.append(indentation + "'@state_action' = '#Assignment'(\n"); + indent(1); + // the variable to assign + avsysml.append(indentation + "'@target' = " + attributeSysMLname(((AvatarQueryOnSignal)asme).getAttribute().getName()) + ",\n"); + // the size of the content of the concerned signal + avsysml.append(indentation + "'@value' = " + methodMap.get(((AvatarQueryOnSignal)asme).getSignal()).getName() + ".'@amount'()\n"); + unindent(1); + avsysml.append(indentation + ")\n"); + unindent(1); + avsysml.append(indentation + ");\n"); + } else + + if(asme instanceof AvatarActionOnSignal){ + if(((AvatarActionOnSignal)asme).isSending()) { + avsysml.append("\n" + indentation + "state " + info.getName() + " : '#AvatarSendState'"); + if (requests.equals("")) // default request + avsysml.append(";\n"); + else // put requests description + avsysml.append(" = '#AvatarSendState'(\n" + requests + "\n" + indentation + ");\n"); + } else { + avsysml.append("\n" + indentation + "state " + info.getName() + " : '#AvatarReceiveState'"); + if (requests.equals("")) // default request + avsysml.append(";\n"); + else + avsysml.append(" = '#AvatarReceiveState'(\n" + requests + "\n" + indentation + ");\n"); + } + } else - if(asme instanceof AvatarExpireTimer){ - avsysml.append("\n" + indentation + "state " + stateMap.get(asme).getName() + " : '#AvatarExpireTimerState'"); - if (requests.equals("")) - avsysml.append(";\n"); - else - avsysml.append(" = '#AvatarExpireTimerState'(\n" + requests + "\n" + indentation + ");\n"); - } + if(asme instanceof AvatarStartState){ + avsysml.append("\n" + indentation + "entry action " + info.getName() + " :'#AvatarStartState'"); + if (requests.equals("")) // default request + avsysml.append(";\n"); + else // put requests description + avsysml.append(" = '#AvatarStartState'(\n" + requests + "\n" + indentation + ");\n"); + } else + + if(asme instanceof AvatarStopState){ // specific mandatory empty request list (implicite) + if(!stopStateDone) + avsysml.append("\n" + indentation + "exit action " + info.getName() + " :'#AvatarStopState';\n"); + stopStateDone = true; + } else + + if(asme instanceof AvatarSetTimer){ + avsysml.append("\n" + indentation + "state " + info.getName() + " : '#AvatarSetTimerState'"); + if (requests.equals("")) // default request + avsysml.append(";\n"); + else // put requests description + avsysml.append(" = '#AvatarSetTimerState'(\n" + requests + "\n" + indentation + ");\n"); + } else - // Transition descriptions - avsysml.append(sysMLtransitions); + if(asme instanceof AvatarResetTimer){ + avsysml.append("\n" + indentation + "state " + info.getName() + " : '#AvatarResetTimerState'"); + if (requests.equals("")) // default request + avsysml.append(";\n"); + else // put requests description + avsysml.append(" = '#AvatarResetTimerState'(\n" + requests + "\n" + indentation + ");\n"); + } else - // PreComm States and their outgoing transition - for (AvatarStateMachineElement aos: requirePreCom) { - StateInfo stateinfo = stateMap.get(aos); - if (aos instanceof AvatarActionOnSignal) { - MethodInfo signalinfo = methodMap.get(((AvatarActionOnSignal)aos).getSignal()); + if(asme instanceof AvatarExpireTimer){ + avsysml.append("\n" + indentation + "state " + info.getName() + " : '#AvatarExpireTimerState'"); + if (requests.equals("")) // default request + avsysml.append(";\n"); + else // put requests description + avsysml.append(" = '#AvatarExpireTimerState'(\n" + requests + "\n" + indentation + ");\n"); + } - if (((AvatarActionOnSignal)aos).isSending()) { - // preComm State - avsysml.append("\n" + indentation + "state " + stateinfo.getPreName() + " : '#AvatarPreSendState' = '#AvatarPreSendState' (\n"); - indent(1); - avsysml.append(indentation + "'@request' =\n"); - indent(1); - avsysml.append(sendRequest2SysML(1, "0", "0", signalinfo, ((AvatarActionOnSignal)aos).getOriginalValues()) + "\n"); - indentation = indentation.substring(2 * indentStepSize); - avsysml.append(indentation + ");\n"); - // its transition - avsysml.append("\n" + indentation + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + - " then " + stateinfo.getName() + - endTransition(0,"","", 1)); - } else { - avsysml.append("\n" + indentation + "state " + stateinfo.getPreName() + " : '#AvatarPreReceiveState' = '#AvatarPreReceiveState' (\n"); - indent(1); - avsysml.append(indentation + "'@request' =\n"); - indent(1); - avsysml.append(receiveRequest2SysML(1, "0", "0", signalinfo) + "\n"); - indentation = indentation.substring(2 * indentStepSize); - avsysml.append(indentation + ");\n"); - // its transition - avsysml.append("\n" + indentation + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + "\n"); - indent(1); - String doAction = receiveActions2SysML(signalinfo, ((AvatarActionOnSignal)aos).getOriginalValues()); - if (doAction.length() == 0) - avsysml.append(indentation + "then " + stateinfo.getName() + - endTransition(0,"","", 1)); - else { - avsysml.append(doAction); - avsysml.append(" then " + stateinfo.getName() + + // put transition declarations ................................................. + avsysml.append(sysMLtransitions); + + // put pre-communication states to add and their single outgoing transition + for (AvatarStateMachineElement aos: requirePreCom) { + // the name of an added states is obtained by StateInfo.getPreName() + // the target of its outgoing transition is the communication state itself (StateInfo.getName()) + // endTransition adds distribution law information at the end of the transition declarations + StateInfo stateinfo = stateMap.get(aos); + if (aos instanceof AvatarActionOnSignal) { + MethodInfo signalinfo = methodMap.get(((AvatarActionOnSignal)aos).getSignal()); + + if (((AvatarActionOnSignal)aos).isSending()) { + // put pre-communication State + avsysml.append("\n" + indentation + "state " + stateinfo.getPreName() + " : '#AvatarPreSendState' = '#AvatarPreSendState' (\n"); + indent(1); + avsysml.append(indentation + "'@request' =\n"); + indent(1); + // sending request from pre-send state to send state + avsysml.append(sendRequest2SysML(1, "0", "0", signalinfo, ((AvatarActionOnSignal)aos).getOriginalValues()) + "\n"); + indentation = indentation.substring(2 * indentStepSize); + avsysml.append(indentation + ");\n"); + // transition from pre-send state to send state + avsysml.append("\n" + indentation + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + + " then " + stateinfo.getName() + endTransition(0,"","", 1)); + } else { + // put pre-communication State + avsysml.append("\n" + indentation + "state " + stateinfo.getPreName() + " : '#AvatarPreReceiveState' = '#AvatarPreReceiveState' (\n"); + indent(1); + avsysml.append(indentation + "'@request' =\n"); + indent(1); + // receiving request from pre-receive state to receive state + avsysml.append(receiveRequest2SysML(1, "0", "0", signalinfo) + "\n"); + indentation = indentation.substring(2 * indentStepSize); + avsysml.append(indentation + ");\n"); + // transition from pre-receive state to receive state + avsysml.append("\n" + indentation + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + "\n"); + indent(1); + // updating target variables with received values + String doAction = receiveActions2SysML(signalinfo, ((AvatarActionOnSignal)aos).getOriginalValues()); + if (doAction.length() == 0) // receive simple signal (without carried value) + avsysml.append(indentation + "then " + stateinfo.getName() + + endTransition(0,"","", 1)); + else { // put updating action + avsysml.append(doAction); + avsysml.append(" then " + stateinfo.getName() + + endTransition(0,"","", 1)); + } + unindent(1); } - unindent(1); - } - } else if (aos instanceof AvatarSetTimer) { - // preComm State + } else if (aos instanceof AvatarSetTimer) { // a special kind of send request + // put pre-communication State avsysml.append("\n" + indentation + "state " + stateinfo.getPreName() + " : '#AvatarPreSendState' = '#AvatarPreSendState' (\n"); indent(1); avsysml.append(indentation + "'@request' =\n"); indent(1); + // put the specific sending request, carrying a value avsysml.append(setTimerRequest2SysML(1, "0", "0", timerBlockSysMLname(((AvatarSetTimer) aos).getTimer().getName()) + ".'@set'" , ((AvatarSetTimer)aos).getTimerValue()) + "\n"); - indentation = indentation.substring(2 * indentStepSize); + unindent(2); avsysml.append(indentation + ");\n"); - // its transition + // put the associated transition avsysml.append("\n" + indentation + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + " then " + stateinfo.getName() + endTransition(0,"","", 1)); - } else if (aos instanceof AvatarResetTimer) { - // preComm State + } else if (aos instanceof AvatarResetTimer) { // a special kind of send request + // put pre-communication State avsysml.append("\n" + indentation + "state " + stateinfo.getPreName() + " : '#AvatarPreSendState' = '#AvatarPreSendState' (\n"); indent(1); avsysml.append(indentation + "'@request' =\n"); indent(1); + // put the specific sending request, carrying no value avsysml.append(resetTimerRequest2SysML(1, "0", "0", timerBlockSysMLname(((AvatarResetTimer) aos).getTimer().getName()) + ".'@reset'" ) + "\n"); indentation = indentation.substring(2 * indentStepSize); avsysml.append(indentation + ");\n"); - // its transition + // put the associated transition avsysml.append("\n" + indentation + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + " then " + stateinfo.getName() + endTransition(0,"","", 1)); - } else if (aos instanceof AvatarExpireTimer) { + } else if (aos instanceof AvatarExpireTimer) { // a special kind of send request + // put pre-communication State avsysml.append("\n" + indentation + "state " + stateinfo.getPreName() + " : '#AvatarPreReceiveState' = '#AvatarPreReceiveState' (\n"); indent(1); avsysml.append(indentation + "'@request' =\n"); indent(1); + // put the specific receiving request, carrying no value avsysml.append(expireTimerRequest2SysML(1, "0", "0", timerBlockSysMLname(((AvatarExpireTimer) aos).getTimer().getName()) + ".'@expire'" ) + "\n"); indentation = indentation.substring(2 * indentStepSize); avsysml.append(indentation + ");\n"); - // its transition + // put the associated transition avsysml.append("\n" + indentation + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + endTransition(0,"","", 1)); indent(1); avsysml.append(indentation + "then " + stateinfo.getName() + ";\n"); unindent(1); + } } + } } + /** distribution law information, to put at the end of associated the transition declarations */ String endTransition(int delayDistributionLaw, String delayExtra1, String delayExtra2, double probability){ - if (delayDistributionLaw == DELAY_UNIFORM_LAW && probability == 1) return ";\n"; + + if (delayDistributionLaw == DELAY_UNIFORM_LAW && probability == 1) return ";\n"; // nothing because default + StringBuffer result = new StringBuffer(" {\n"); indent(1); + + // put distribution law result.append(indentation + "attribute '@delayDistributionLaw' : String = \"" + DISTRIBUTION_LAWS[delayDistributionLaw] + "\";\n"); - if (probability != 1) - result.append(indentation + "attribute '@weight' : Real = " + probability + ";\n"); + + // put distribution law first parameter (if exists) if (NB_OF_EXTRA_ATTRIBUTES[delayDistributionLaw] > 0) result.append(indentation + "attribute '" + LABELS_OF_EXTRA_ATTRIBUTES_1[delayDistributionLaw] + "' : String = \"" + delayExtra1 + "\";\n"); + + // put distribution law second parameter (if exists) if (NB_OF_EXTRA_ATTRIBUTES[delayDistributionLaw] > 1) result.append(indentation + "attribute '" + LABELS_OF_EXTRA_ATTRIBUTES_2[delayDistributionLaw] + "' : String = \"" + delayExtra2 + "\";\n"); + + // put probability (if different from the default one) + if (probability != DEFAULT_PROBABILITY) + result.append(indentation + "attribute '@weight' : Real = " + probability + ";\n"); + unindent(1); result.append(indentation + "}\n"); return result.toString(); } - void transitionsAndRequests(String srcName, List<AvatarStateMachineElement> nexts, String poolName) { + /** computes transition declarations and request descriptions for the outgoing transitions of the state. Put the corresponding + * texts in the sysMLtransitions and sysMLrequests StringBuffers. While doing this, identify communication states that require + * an added pre-communication state. + * @param srcName name of the source state + * @param nexts outgoing transitions from the source state + * @param poolName "pool" or "request" depending on the number of allowed outgoing transitions + * @param stateMap to find state names + */ + void transitionsAndRequests(String srcName, List<AvatarStateMachineElement> nexts, String poolName, + HashMap<AvatarStateMachineElement,StateInfo> stateMap) { + // initialization requirePreCom.clear(); sysMLtransitions.delete(0, sysMLtransitions.length()); sysMLrequests.delete(0, sysMLrequests.length()); + int nb = nexts.size(); - if (nb == 0) { + if (nb == 0) { // no transition sysMLrequests.append(indentation + poolName + " = null\n"); return; } - if (nb == 1) { + if (nb == 1) { // no parenthesis required indent(1); - transitionAndRequest(srcName, (AvatarTransition)nexts.get(0), 0); + // handle the single transition + transitionAndRequest(srcName, (AvatarTransition)nexts.get(0), 0, stateMap); unindent(1); - if(sysMLrequests.toString().trim().equals("'#immediate_request'")) { + if(sysMLrequests.toString().trim().equals("'#immediate_request'")) { // remove because it is the default sysMLrequests.delete(0, sysMLrequests.length()); return; } + // wrap without parenthesis sysMLrequests.insert(0, indentation + poolName + " =\n"); return; } + // more than one request -> list between parenthesis indent(1); + // put list for(int i=0; i<nb; i++){ - transitionAndRequest(srcName, (AvatarTransition)nexts.get(i), i+1); + transitionAndRequest(srcName, (AvatarTransition)nexts.get(i), i+1, stateMap); if(i != nb-1) sysMLrequests.append(",\n"); else sysMLrequests.append("\n"); } unindent(1); + // wrap with parenthesis sysMLrequests.insert(0, indentation + poolName + " = (\n"); sysMLrequests.append(indentation + ")"); } + private String clean_guard(String _guard) { int open = _guard.indexOf('['); int close = _guard.lastIndexOf(']'); @@ -1043,7 +1131,7 @@ public class Avatar2SysML { else return _guard; } // index is 0 if transition is alone - void transitionAndRequest(String srcName, AvatarTransition at, int index){ + void transitionAndRequest(String srcName, AvatarTransition at, int index, HashMap<AvatarStateMachineElement, StateInfo> stateMap){ int transindex = ((index == 0) ? 1 : index); // identifying cases -- GitLab