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