/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille * * ludovic.apvrille AT enst.fr * * This software is a computer program whose purpose is to allow the * edition of TURTLE analysis, design and deployment diagrams, to * allow the generation of RT-LOTOS or Java code from this diagram, * and at last to allow the analysis of formal validation traces * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP * from INRIA Rhone-Alpes. * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ package avatartranslator.tosysmlv2; import avatartranslator.*; import static avatartranslator.AvatarTransition.*; import static avatartranslator.tosysmlv2.Avatar2SysMLNames.*; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.ArrayList; public class Avatar2SysML { /** * Memorized while declaring channels, to be reused for generating states */ class MethodInfo { private String name; private String msgtype; // null for methods that are not signals private ArrayList<String> fieldNames; private ArrayList<Integer> fieldTypes; private ArrayList<AvatarDataType> dataTypes; private int returnType; private AvatarDataType returnDataType; MethodInfo(String _name) { // for void methods name = _name; msgtype = null; fieldNames = new ArrayList<String>(); fieldTypes = new ArrayList<Integer>(); dataTypes = new ArrayList<AvatarDataType>(); returnType = -1; returnDataType = null; } MethodInfo(String _name, int _returnType, AvatarDataType dt) { // for non-void methods name = _name; msgtype = null; fieldNames = new ArrayList<String>(); fieldTypes = new ArrayList<Integer>(); dataTypes = new ArrayList<AvatarDataType>(); returnType = _returnType; if (_returnType != AvatarDataType.DATATYPE) returnDataType = null; else returnDataType = dt; } MethodInfo(String _name, String _msgtype) { // for signals name = _name; msgtype = _msgtype; fieldNames = new ArrayList<String>(); fieldTypes = new ArrayList<Integer>(); dataTypes = new ArrayList<AvatarDataType>(); returnType = -1; returnDataType = null; } public void addField(String _fieldName, int _type, AvatarDataType _dt){ if (_type == AvatarDataType.DATATYPE) dataTypes.add(_dt); else if (!(_type == AvatarDataType.BOOLEAN || _type == AvatarDataType.INTEGER)) return; // unknown type else dataTypes.add(null); fieldNames.add(_fieldName); fieldTypes.add(_type); } public int getArity() { return fieldNames.size(); } public String getName(){ return name; } public String getMessageType(){ return msgtype; } public int getReturnType(){ return returnType; } public AvatarDataType getReturnDataType(){ return returnDataType; } public String getFieldName(int i){ return fieldNames.get(i); } public int getFieldType(int i){ return fieldTypes.get(i); } public AvatarDataType getDataType(int i){ return dataTypes.get(i); } } /** * Memorized while naming states, to be reused for generating states */ class StateInfo { private String name; private String prename = ""; StateInfo(String _name) { name = _name; } StateInfo(String _name, String _prename) { name = _name; prename = _prename; } public String getName(){ return name; } public String getPreName(){ return prename; } } public Avatar2SysML(AvatarSpecification _avspec) { avspec = _avspec; } private AvatarSpecification avspec; StringBuffer avsysml; HashSet<AvatarSignal> fifoSet = new HashSet<AvatarSignal>(); HashMap<AvatarMethod, MethodInfo> methodMap = new HashMap<AvatarMethod, MethodInfo>(); HashMap<AvatarStateMachineElement, StateInfo> stateMap = new HashMap<AvatarStateMachineElement, StateInfo>(); ArrayList<AvatarStateMachineElement> stateList = new ArrayList<AvatarStateMachineElement>(); ArrayList<AvatarAttribute> timerList = new ArrayList<AvatarAttribute>(); void searchCountSignals() { fifoSet.clear(); for(AvatarBlock block: avspec.getListOfBlocks()) { for(AvatarStateMachineElement sme : block.getStateMachine().getListOfElements()) { if(sme instanceof AvatarQueryOnSignal) fifoSet.add(((AvatarQueryOnSignal) sme).getSignal()); } } } ArrayList<String> blockChain = new ArrayList<String>(); void chainBlock(String _block) { blockChain.add(_block); } void unchainBlock() { if(blockChain.size() > 0) blockChain.remove(blockChain.size() - 1); } void blocklink() { int size = blockChain.size(); if (size < 2) return; StringBuffer chain = new StringBuffer(); for (int i=0; i < size-1; i++){ chain.append(blockChain.get(i) + "."); } chain.append(blockChain.get(size - 1)); blockLinks.append( indentStep + "part " + blockChain.get(size - 1) + " : '#AvatarBlock' :> " + chain.toString() + " = " + chain.toString() + ";\n" ); } StringBuffer blockLinks = new StringBuffer(); String indentStep = " "; int indentStepSize = 4; String indent = ""; String header = "package AvatarInstance {\n" + indentStep + "import ScalarValues::String;\n" + indentStep + "import ScalarValues::Positive;\n" + indentStep + "import ScalarValues::Integer;\n" + indentStep + "import ScalarValues::Boolean;\n" + indentStep + "import ScalarValues::Real;\n" + indentStep + "import AvatarBlockTypes::*;\n" + indentStep + "import AvatarCommunication::*;\n"; StringBuffer avatar2SysML() { methodMap.clear(); stateMap.clear(); stateList.clear(); blockChain.clear(); blockLinks = new StringBuffer(indentStep + "// Block Shortcut Links $$$$$$$$$$$$\n"); avsysml = new StringBuffer(header); indent += indentStep; searchCountSignals();; dataTypes2SysML(); communications2SysML(); blocks2SysML(); avsysml.append(blockLinks); avsysml.append("}\n"); return avsysml; } String removeFieldName(String fullName, AvatarDataType dt) { if (fullName == null || dt.getNbFields() == 0) return fullName; String fieldString = dt.getFieldString(0); int prefixSize = fullName.length() - fieldString.length() - 2; if (fieldString.equals(fullName.substring(fullName.length() - fieldString.length())) && prefixSize >= 0) return fullName.substring(0, prefixSize); else return null; } String removeFieldName(AvatarAttribute aa) { if (aa.getDataType() == null) return null; return removeFieldName(aa.getName(), aa.getDataType()); } void dataTypes2SysML(){ if (avspec.getDataTypes() == null || avspec.getDataTypes().size() == 0) return; avsysml.append("\n" + indent + "// DATATYPES $$$$$$$$$$$$$$$$$$$$$$$$\n"); for(AvatarDataType dt : avspec.getDataTypes()){ avsysml.append("\n" + indent + "attribute def " + dataTypeSysMLname(dt.getName()) + " :> '#AvatarDataType'"); int nbFields = dt.getNbFields(); if (nbFields == 0) avsysml.append(";\n"); else { avsysml.append(" { \n"); indent += indentStep; for (int i = 0; i < nbFields; i++) { avsysml.append( indent + "attribute " + fieldSysMLname(dt.getFieldName(i)) + " : " ); if (dt.getFieldType(i) == AvatarDataType.BOOLEAN) avsysml.append("Boolean;\n"); else if (dt.getFieldType(i) == AvatarDataType.INTEGER) avsysml.append("Integer;\n"); else avsysml.append(dt.getDataTypeNameName(i) + ";\n"); } indent = indent.substring(indentStepSize); avsysml.append(indent + "}\n"); } } } void communications2SysML(){ int nbfiforelNumber = 0; int bfiforelNumber = 0; int syncrelNumber = 0; if (avspec.getRelations() == null || avspec.getRelations().size() == 0) return; avsysml.append("\n" + indent + "// COMMUNICATIONS $$$$$$$$$$$$$$$$$$$$$$$$\n"); for(AvatarRelation ar: avspec.getRelations()) { // parameters depending on relation type ============== int relationType; int relationNumber; String relationConstructor; String relationParameters = null; String channelConstructor; // computine parameters depending on relation type ============== // if (ar.isAMS()) throw exception String blk1 = ar.getBlock1().getName(); String blk2 = ar.getBlock2().getName(); String blk1SysMLname = blockSysMLname(blk1); String blk2SysMLname = blockSysMLname(blk2); relationParameters = "('@block1' = " + blk1SysMLname + ", '@block2' = " + blk2SysMLname; if (! ar.isAsynchronous()) { // sync relation relationType = SYNC; relationNumber = syncrelNumber++; relationConstructor = "'#Sync_Rel'"; channelConstructor = "'#Sync'"; if(ar.isPrivate()) relationParameters += ", '@private'=true)"; } else { // fifo relation if(ar.isPrivate()) // default: false if(ar.isLossy()) // default: false if(ar.getSizeOfFIFO() > 1) // default size: 1 relationParameters += ", '@private'=true, '@lossy'=true, '@max_size'=" + ar.getSizeOfFIFO() + ")"; else relationParameters += ", '@private'=true, '@lossy'=true)"; else if(ar.getSizeOfFIFO() > 1) // default size: 1 relationParameters += ", '@private'=true, '@max_size'=" + ar.getSizeOfFIFO() + ")"; else relationParameters += ", '@private'=true)"; else if(ar.isLossy()) // default: false if(ar.getSizeOfFIFO() > 1) // default size: 1 relationParameters += ", '@lossy'=true, '@max_size'=" + ar.getSizeOfFIFO() + ")"; else relationParameters += ", '@lossy'=true)"; else if(ar.getSizeOfFIFO() > 1) // default size: 1 relationParameters += ", '@max_size'=" + ar.getSizeOfFIFO() + ")"; if (ar.isBlocking()) { // blocking fifo relation relationType = BFIFO; relationNumber = bfiforelNumber++; relationConstructor = "'#Bfifo_Rel'"; channelConstructor = "'#Bfifo'"; } else { // non blocking fifo relation relationType = NBFIFO; relationNumber = nbfiforelNumber++; relationConstructor = "'#NBfifo_Rel'"; channelConstructor = "'#NBfifo'"; } } // general type-independent generation ============== String relationSYSMLname = relationSysMLname(blk1, blk2, relationType, relationNumber); // relation declaration -------------------- avsysml.append("\n" + indent + "// Relation " + relationSYSMLname + "=============\n"); avsysml.append(indent + "part " + relationSYSMLname + ": " + relationConstructor); if(relationParameters != null) avsysml.append(" = " + relationConstructor + relationParameters); avsysml.append(";\n"); // Channels and associated Messages declarations ---------------- int relationSize = ar.getSignals1().size(); for(int i=0; i<relationSize; i++) { AvatarSignal sig1 = ar.getSignals1().get(i); AvatarSignal sig2 = ar.getSignals2().get(i); boolean in2out = (sig1.getInOut() == AvatarSignal.IN); // to remove String channelName = channelName(blk1, blk2, sig1.getName(), sig2.getName(), in2out); String channelSYSMLname = channelSysMLname(channelName(blk1, blk2, sig1.getName(), sig2.getName(), in2out), relationType); String sig1SYSMLname = signalSysMLname(sig1.getName()); String sig2SYSMLname = signalSysMLname(sig2.getName()); String message1SYSMLname = messageSysMLname(blk1,sig1.getName()); String message2SYSMLname = messageSysMLname(blk2,sig2.getName()); MethodInfo sig1Info = new MethodInfo(sig1SYSMLname, message1SYSMLname); MethodInfo sig2Info = new MethodInfo(sig2SYSMLname, message2SYSMLname); // Channel declaration ......................... avsysml.append("\n" + indent + "// Channel " + channelSYSMLname + "-------------\n"); avsysml.append(indent + "part " + channelSYSMLname + " : " + channelConstructor + " = " + channelConstructor + "('@relation' = " + relationSYSMLname + ");\n"); if (in2out) { avsysml.append(indent + "binding : '#InSignalBinding' bind " + blk1SysMLname + "." + sig1SYSMLname + " = " + channelSYSMLname + ";\n"); avsysml.append(indent + "binding : '#OutSignalBinding' bind " + blk2SysMLname + "." + sig2SYSMLname + " = " + channelSYSMLname + ";\n"); } else { avsysml.append(indent + "binding : '#OutSignalBinding' bind " + blk1SysMLname + "." + sig1SYSMLname + " = " + channelSYSMLname + ";\n"); avsysml.append(indent + "binding : '#InSignalBinding' bind " + blk2SysMLname + "." + sig2SYSMLname + " = " + channelSYSMLname + ";\n"); } // Message declaration ......................... StringBuffer msg1Buf = new StringBuffer(indent + "\n// Message of signal " + blk1SysMLname + "." + sig1SYSMLname + "............\n"); StringBuffer msg2Buf = new StringBuffer(indent + "\n// Message of signal " + blk2SysMLname + "." + sig2SYSMLname + "............\n"); if (in2out) { msg1Buf.append(indent + "part def " + message1SYSMLname + " :> '#InMessage' {\n" + indent + indentStep + "private part '@channel' : '#Channel' = " + channelSYSMLname + ";\n"); msg2Buf.append(indent + "part def " + message2SYSMLname + " :> '#OutMessage', " + message1SYSMLname + " {\n"); } else { msg1Buf.append(indent + "part def " + message1SYSMLname + " :> '#OutMessage', " + message2SYSMLname + " {\n"); msg2Buf.append(indent + "part def " + message2SYSMLname + " :> '#InMessage' {\n" + indent + indentStep + "private part '@channel' : '#Channel' = " + channelSYSMLname + ";\n"); } indent += indentStep; // message fields. SysML names preserve Avatar sender and receiver names int channelSize = sig1.getListOfAttributes().size(); int j=0; int type; String attributeType; String fieldName1; String fieldName2; while (j < channelSize ) { // browse channels' parameters AvatarDataType dataType = sig1.getListOfAttributes().get(j).getDataType(); if (dataType == null) { attributeType = (sig1.getListOfAttributes().get(j).isInt() ? "Integer;\n" : "Boolean;\n"); type = (sig1.getListOfAttributes().get(j).isInt() ? AvatarDataType.INTEGER : AvatarDataType.BOOLEAN); fieldName1 = fieldSysMLname(sig1.getListOfAttributes().get(j).getName()); fieldName2 = fieldSysMLname(sig2.getListOfAttributes().get(j).getName()); j++; } else { attributeType = dataTypeSysMLname(dataType.getName()) + ";\n"; type = AvatarDataType.DATATYPE; fieldName1 = fieldSysMLname(removeFieldName(sig1.getListOfAttributes().get(j))); fieldName2 = fieldSysMLname(removeFieldName(sig2.getListOfAttributes().get(j))); j += dataType.getFullSize(); } if (in2out) { msg1Buf.append(indent + "attribute " + fieldName1 + " : " + attributeType); msg2Buf.append(indent + "attribute " + fieldName2 + " redefines " + fieldName1 + ";\n"); } else { msg1Buf.append(indent + "attribute " + fieldName1 + " redefines " + fieldName2 + ";\n"); msg2Buf.append(indent + "attribute " + fieldName2 + " : " + attributeType); } sig1Info.addField(fieldName1, type, dataType); sig2Info.addField(fieldName2, type, dataType); } indent = indent.substring(indentStepSize); msg1Buf.append(indent + "}\n"); msg2Buf.append(indent + "}\n"); if (in2out) { avsysml.append(msg1Buf); avsysml.append(msg2Buf); } else { avsysml.append(msg2Buf); avsysml.append(msg1Buf); } methodMap.put(sig1,sig1Info); methodMap.put(sig2,sig2Info); } } } void method2SysML(AvatarMethod am){ // "return tuple" not handled String returnType; List<AvatarAttribute> returns = am.getListOfReturnAttributes(); AvatarDataType returnDataType; MethodInfo methodInfo; if(returns.size() == 0) { returnType = null; methodInfo = new MethodInfo(methodSysMLname(am.getName())); } else { returnDataType = returns.get(0).getDataType(); if (returnDataType == null) { String avatarType = returns.get(0).getType().getStringType(); if (avatarType.equals("int")) { returnType = "Integer"; methodInfo = new MethodInfo(methodSysMLname(am.getName()), AvatarDataType.INTEGER, null); } else { returnType = "Boolean"; methodInfo = new MethodInfo(methodSysMLname(am.getName()), AvatarDataType.BOOLEAN, null); } } else { returnType = dataTypeSysMLname(returnDataType.getName()); methodInfo = new MethodInfo(methodSysMLname(am.getName()), AvatarDataType.DATATYPE, returnDataType); } } if (returnType == null) avsysml.append(indent + "action " + methodSysMLname(am.getName()) + ": '#AvatarVoidMethod' {\n"); else avsysml.append(indent + "calc " + methodSysMLname(am.getName()) + ": '#AvatarCalcMethod' {\n"); indent += indentStep; int j = 0; int nbFields = am.getListOfAttributes().size(); while (j < nbFields) { AvatarAttribute aa = am.getListOfAttributes().get(j); AvatarDataType fieldDataType = aa.getDataType(); if (fieldDataType == null) { if (aa.isInt()) { avsysml.append(indent + "attribute " + fieldSysMLname(aa.getName()) + " : Integer;\n"); methodInfo.addField(fieldSysMLname(aa.getName()), AvatarDataType.INTEGER, null); } else { avsysml.append(indent + "attribute " + fieldSysMLname(aa.getName()) + " : Boolean;\n"); methodInfo.addField(fieldSysMLname(aa.getName()), AvatarDataType.BOOLEAN, null); } j++; } else { avsysml.append(indent + "attribute " + fieldSysMLname(removeFieldName(aa)) + " : " + dataTypeSysMLname(fieldDataType.getName())+ ";\n"); methodInfo.addField(fieldSysMLname(aa.getName()), AvatarDataType.DATATYPE, fieldDataType); j += fieldDataType.getFullSize(); } } if (returnType != null) avsysml.append(indent + "return : " + returnType + ";\n"); indent = indent.substring(indentStepSize); avsysml.append(indent + "}\n"); methodMap.put(am, methodInfo); } void signal2SysML(AvatarSignal as){ avsysml.append(indent + "part " + methodMap.get(as).getName() + " : " + (fifoSet.contains(as) ? "'#Fifo'" : "'#Channel'") + ";\n"); } // handling one block void block2SysML(AvatarBlock block){ String blockSYSMLname = blockSysMLname(block.getName()); timerList.clear(); chainBlock(blockSYSMLname); blocklink(); // block header -------------------- avsysml.append("\n" + indent + "// Block " + blockSYSMLname + "=============\n"); avsysml.append(indent + "part " + blockSYSMLname + " : '#AvatarBlock' {\n"); indent += indentStep; // attributes -------------------- if (block.getAttributes() != null && block.getAttributes().size() != 0) { avsysml.append("\n" + indent + "// Attributes ---------------------\n"); int j = 0; int nbAttributes = block.getAttributes().size(); while(j < nbAttributes) { AvatarAttribute aa = block.getAttributes().get(j); if (aa.isTimer()) { timerList.add(aa); j++; } else { AvatarDataType dataType = aa.getDataType(); if (dataType == null) { avsysml.append(indent + "attribute " + attributeSysMLname(aa.getName()) + " : "); if (aa.isInt()) avsysml.append("Integer"); else avsysml.append("Boolean"); if (aa.hasInitialValue()) avsysml.append(" := " + aa.getInitialValue().trim()); avsysml.append(";\n"); j++; } else { avsysml.append(indent + "attribute " + attributeSysMLname(removeFieldName(aa)) + " : " + dataTypeSysMLname(dataType.getName()) + ";\n"); j += dataType.getFullSize(); } } } } // constants -------------------- if (block.getConstants() != null && block.getConstants().size() != 0) { avsysml.append("\n" + indent + "// Constants ---------------------\n"); int j = 0; int nbConstants = block.getConstants().size(); while(j < nbConstants) { AvatarAttribute cs = block.getConstants().get(j); AvatarDataType dataType = cs.getDataType(); if (dataType == null) { avsysml.append(indent + "readonly attribute " + attributeSysMLname(cs.getName()) + " : "); if (cs.isInt()) avsysml.append("Integer"); else avsysml.append("Boolean"); if (cs.hasInitialValue()) avsysml.append(" := " + cs.getInitialValue().trim()); avsysml.append(";\n"); j++; } else { avsysml.append(indent + "readonly attribute " + attributeSysMLname(removeFieldName(cs)) + " : " + dataTypeSysMLname(dataType.getName()) + ";\n"); j += dataType.getFullSize(); } } } // methods -------------------- if (block.getMethods() != null && block.getMethods().size() != 0) { avsysml.append("\n" + indent + "// Methods ---------------------\n"); for (AvatarMethod am : block.getMethods()) method2SysML(am); } if (block.getSignals() != null && block.getSignals().size() != 0) { avsysml.append("\n" + indent + "// Signals ---------------------\n"); for (AvatarSignal as : block.getSignals()) signal2SysML(as); } // timers ------------------- if (timerList != null && timerList.size() != 0) { avsysml.append("\n" + indent + "// Timers ---------------------\n"); for (AvatarAttribute timer : timerList) avsysml.append(indent + "part " + timerBlockSysMLname(timer.getName()) + ": '#AvatarTimer' = '#AvatarTimer'();\n"); } // state-machine -------------------- avsysml.append("\n" + indent + "// state-machine -------------------\n"); statemachine2SysML(block.getStateMachine()); // sub-blocks ------------------- List<AvatarBlock> subBlockList = new ArrayList<AvatarBlock>(); for(AvatarBlock blk: avspec.getListOfBlocks()) { if (blk.getFather() == block) subBlockList.add(blk); } if (subBlockList != null && subBlockList.size() != 0) { avsysml.append("\n" + indent + "// Sub-Blocks øøøøøøøøøøøøøøøøøøøøøøø\n"); for (AvatarBlock blk : subBlockList) if (blk.getFather() == block) block2SysML(blk); } indent = indent.substring(indentStepSize); avsysml.append(indent + "}\n"); unchainBlock(); } // handling all blocks void blocks2SysML(){ avsysml.append("\n" + indent + "// 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 int randomNumber = 0; int countNumber = 0; int sendNumber = 0; int receiveNumber = 0; int setNumber = 0; int resetNumber = 0; int expireNumber = 0; for (AvatarStateMachineElement asme : asm.getListOfElements()) { StateInfo stateinfo; 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 AvatarActionOnSignal) { if(((AvatarActionOnSignal)asme).isSending()) stateinfo = new StateInfo( 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), presetTimerStateSysMLname(((AvatarTimerOperator) asme).getTimer().getName(), setNumber++)); } 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), 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); stateMap.put(asme, stateinfo); } avsysml.append(indent + "exhibit state '@statemachine' : '#AvatarStateMachine' {\n"); indent += indentStep; // generate SysML states with associated transitions stopState = false; for (AvatarStateMachineElement asme : stateList) state2SysML(asme); indent = indent.substring(indentStepSize); avsysml.append(indent + "}\n"); } StringBuffer sysMLtransitions = new StringBuffer(); StringBuffer sysMLrequests = new StringBuffer(); List<AvatarStateMachineElement> requirePreCom = new ArrayList<AvatarStateMachineElement>(); void state2SysML(AvatarStateMachineElement asme){ indent += indentStep; transitionsAndRequests(stateMap.get(asme).getName(), asme.getNexts(), ((asme instanceof AvatarState) ? "'@pool'" : "'@request'")); indent = indent.substring(indentStepSize); String requests = sysMLrequests.toString(); // State Description, depending on state type if(asme instanceof AvatarState){ avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarStandardState'"); if (requests.equals("")) avsysml.append(";\n"); else avsysml.append(" = '#AvatarStandardState'(\n" + requests + "\n" + indent + ");\n"); } else if(asme instanceof AvatarRandom){ avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarRandomState' = '#AvatarRandomState'(\n"); if (!requests.equals("")) avsysml.append(requests + ",\n"); indent += indentStep; avsysml.append(indent + "'@state_action' = '#Assignment'(\n"); indent += indentStep; avsysml.append(indent + "'@target' = " + attributeSysMLname(((AvatarRandom)asme).getVariable()) + ",\n"); avsysml.append(indent + "'@value' = '#bound_random'(" + expr2SysML(((AvatarRandom)asme).getMinValue()) + ", " + expr2SysML(((AvatarRandom)asme).getMaxValue()) +")\n"); indent = indent.substring(indentStepSize); avsysml.append(indent + ")\n"); indent = indent.substring(indentStepSize); avsysml.append(indent + ");\n"); } else if(asme instanceof AvatarQueryOnSignal){ avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarCountState' = '#AvatarCountState'(\n"); if (!requests.equals("")) avsysml.append(requests + ",\n"); indent += indentStep; avsysml.append(indent + "'@state_action' = '#Assignment'(\n"); indent += indentStep; avsysml.append(indent + "'@target' = " + attributeSysMLname(((AvatarQueryOnSignal)asme).getAttribute().getName()) + ",\n"); avsysml.append(indent + "'@value' = " + methodMap.get(((AvatarQueryOnSignal)asme).getSignal()).getName() + ".'@amount'()\n"); indent = indent.substring(indentStepSize); avsysml.append(indent + ")\n"); indent = indent.substring(indentStepSize); avsysml.append(indent + ");\n"); } else if(asme instanceof AvatarActionOnSignal){ if(((AvatarActionOnSignal)asme).isSending()) { avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarSendState'"); if (requests.equals("")) avsysml.append(";\n"); else avsysml.append(" = '#AvatarSendState'(\n" + requests + "\n" +indent + ");\n"); } else { avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarReceiveState'"); if (requests.equals("")) avsysml.append(";\n"); else avsysml.append(" = '#AvatarReceiveState'(\n" + requests + "\n" + indent + ");\n"); } } else if(asme instanceof AvatarStartState){ avsysml.append("\n" + indent + "entry action " + stateMap.get(asme).getName() + " :'#AvatarStartState'"); if (requests.equals("")) avsysml.append(";\n"); else avsysml.append(" = '#AvatarStartState'(\n" + requests + "\n" + indent + ");\n"); } else if(asme instanceof AvatarStopState){ if(! stopState) avsysml.append("\n" + indent + "exit action " + stateMap.get(asme).getName() + " :'#AvatarStopState';\n"); stopState = true; } else if(asme instanceof AvatarSetTimer){ avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarSetTimerState'"); if (requests.equals("")) avsysml.append(";\n"); else avsysml.append(" = '#AvatarSetTimerState'(\n" + requests + "\n" + indent + ");\n"); } else if(asme instanceof AvatarResetTimer){ avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarResetTimerState'"); if (requests.equals("")) avsysml.append(";\n"); else avsysml.append(" = '#AvatarResetTimerState'(\n" + requests + "\n" + indent + ");\n"); } else if(asme instanceof AvatarExpireTimer){ avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarExpireTimerState'"); if (requests.equals("")) avsysml.append(";\n"); else avsysml.append(" = '#AvatarExpireTimerState'(\n" + requests + "\n" + indent + ");\n"); } // Transition descriptions avsysml.append(sysMLtransitions); // 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 (((AvatarActionOnSignal)aos).isSending()) { // preComm State avsysml.append("\n" + indent + "state " + stateinfo.getPreName() + " : '#AvatarPreSendState' = '#AvatarPreSendState' (\n"); indent += indentStep; avsysml.append(indent + "'@request' =\n"); indent += indentStep; avsysml.append(sendRequest2SysML(1, "0", "0", signalinfo, ((AvatarActionOnSignal)aos).getValues()) + "\n"); indent = indent.substring(2 * indentStepSize); avsysml.append(indent + ");\n"); // its transition avsysml.append("\n" + indent + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + " then " + stateinfo.getName() + endTransition(0,"","", 1)); } else { avsysml.append("\n" + indent + "state " + stateinfo.getPreName() + " : '#AvatarPreReceiveState' = '#AvatarPreReceiveState' (\n"); indent += indentStep; avsysml.append(indent + "'@request' =\n"); indent += indentStep; avsysml.append(receiveRequest2SysML(1, "0", "0", signalinfo) + "\n"); indent = indent.substring(2 * indentStepSize); avsysml.append(indent + ");\n"); // its transition avsysml.append("\n" + indent + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + "\n"); indent += indentStep; String doAction = receiveActions2SysML(signalinfo, ((AvatarActionOnSignal)aos).getValues()); if (doAction.length() == 0) avsysml.append(indent + "then " + stateinfo.getName() + endTransition(0,"","", 1)); else { avsysml.append(doAction); avsysml.append(" then " + stateinfo.getName() + endTransition(0,"","", 1)); } indent = indent.substring(indentStepSize); } } else if (aos instanceof AvatarSetTimer) { // preComm State avsysml.append("\n" + indent + "state " + stateinfo.getPreName() + " : '#AvatarPreSendState' = '#AvatarPreSendState' (\n"); indent += indentStep; avsysml.append(indent + "'@request' =\n"); indent += indentStep; avsysml.append(setTimerRequest2SysML(1, "0", "0", timerBlockSysMLname(((AvatarSetTimer) aos).getTimer().getName()) + ".'@set'" , ((AvatarSetTimer)aos).getTimerValue()) + "\n"); indent = indent.substring(2 * indentStepSize); avsysml.append(indent + ");\n"); // its transition avsysml.append("\n" + indent + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + " then " + stateinfo.getName() + endTransition(0,"","", 1)); } else if (aos instanceof AvatarResetTimer) { // preComm State avsysml.append("\n" + indent + "state " + stateinfo.getPreName() + " : '#AvatarPreSendState' = '#AvatarPreSendState' (\n"); indent += indentStep; avsysml.append(indent + "'@request' =\n"); indent += indentStep; avsysml.append(resetTimerRequest2SysML(1, "0", "0", timerBlockSysMLname(((AvatarResetTimer) aos).getTimer().getName()) + ".'@reset'" ) + "\n"); indent = indent.substring(2 * indentStepSize); avsysml.append(indent + ");\n"); // its transition avsysml.append("\n" + indent + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + " then " + stateinfo.getName() + endTransition(0,"","", 1)); } else if (aos instanceof AvatarExpireTimer) { avsysml.append("\n" + indent + "state " + stateinfo.getPreName() + " : '#AvatarPreReceiveState' = '#AvatarPreReceiveState' (\n"); indent += indentStep; avsysml.append(indent + "'@request' =\n"); indent += indentStep; avsysml.append(expireTimerRequest2SysML(1, "0", "0", timerBlockSysMLname(((AvatarExpireTimer) aos).getTimer().getName()) + ".'@expire'" ) + "\n"); indent = indent.substring(2 * indentStepSize); avsysml.append(indent + ");\n"); // its transition avsysml.append("\n" + indent + "transition : '#AvatarTransition' first " + stateinfo.getPreName() + endTransition(0,"","", 1)); indent += indentStep; avsysml.append(indent + "then " + stateinfo.getName() + ";\n"); indent = indent.substring(indentStepSize); } } } String endTransition(int delayDistributionLaw, String delayExtra1, String delayExtra2, double probability){ if (delayDistributionLaw == DELAY_UNIFORM_LAW && probability == 1) return ";\n"; StringBuffer result = new StringBuffer(" {\n"); indent += indentStep; result.append(indent + "attribute '@delayDistributionLaw' : String = \"" + DISTRIBUTION_LAWS[delayDistributionLaw] + "\";\n"); if (probability != 1) result.append(indent + "attribute '@weight' : Real = " + probability + ";\n"); if (NB_OF_EXTRA_ATTRIBUTES[delayDistributionLaw] > 0) result.append(indent + "attribute '" + LABELS_OF_EXTRA_ATTRIBUTES_1[delayDistributionLaw] + "' : String = \"" + delayExtra1 + "\";\n"); if (NB_OF_EXTRA_ATTRIBUTES[delayDistributionLaw] > 1) result.append(indent + "attribute '" + LABELS_OF_EXTRA_ATTRIBUTES_2[delayDistributionLaw] + "' : String = \"" + delayExtra2 + "\";\n"); indent = indent.substring(indentStepSize); result.append(indent + "}\n"); return result.toString(); } void transitionsAndRequests(String srcName, List<AvatarStateMachineElement> nexts, String poolName) { requirePreCom.clear(); sysMLtransitions.delete(0, sysMLtransitions.length()); sysMLrequests.delete(0, sysMLrequests.length()); int nb = nexts.size(); if (nb == 0) { sysMLrequests.append(indent + poolName + " = null\n"); return; } if (nb == 1) { indent += indentStep; transitionAndRequest(srcName, (AvatarTransition)nexts.get(0), 0); indent = indent.substring(indentStepSize); if(sysMLrequests.toString().trim().equals("'#immediate_request'")) { sysMLrequests.delete(0, sysMLrequests.length()); return; } sysMLrequests.insert(0, indent + poolName + " =\n"); return; } indent += indentStep; for(int i=0; i<nb; i++){ transitionAndRequest(srcName, (AvatarTransition)nexts.get(i), i+1); if(i != nb-1) sysMLrequests.append(",\n"); else sysMLrequests.append("\n"); } indent = indent.substring(indentStepSize); sysMLrequests.insert(0, indent + poolName + " = (\n"); sysMLrequests.append(indent + ")"); } // index is 0 if transition is alone void transitionAndRequest(String srcName, AvatarTransition at, int index){ int transindex = ((index == 0) ? 1 : index); // identifying cases boolean guarded = !at.hasNonDeterministicGuard(); AvatarStateMachineElement target = at.getNext(0); String tgtName; int requestType = 0; // 0:trivial, 1:Send, 2:Receive, 3:SetTimer, 4: ResetTimer, 5:ExpireTimer if((at.getActions()!=null && at.getActions().size()!=0) && (target instanceof AvatarActionOnSignal || target instanceof AvatarTimerOperator)) { // preCommunication Required requirePreCom.add(target); tgtName = stateMap.get(target).getPreName(); } else { tgtName = stateMap.get(target).getName(); if(target instanceof AvatarActionOnSignal){ if (((AvatarActionOnSignal)target).isSending()) requestType = 1; else requestType = 2; } else if (target instanceof AvatarSetTimer) requestType = 3; else if (target instanceof AvatarResetTimer) requestType = 4; else if (target instanceof AvatarExpireTimer) requestType = 5; } // computing request if (guarded) { sysMLrequests.append(indent + "if " + expr2SysML(((AvatarTransition)at).getGuard().toString()) + " ?\n"); indent += indentStep; } String minDelay = ( at.getMinDelay().length()==0 ? "0" : at.getMinDelay().toString() ); String maxDelay = ( at.getMaxDelay().length()==0 ? "0" : at.getMaxDelay().toString() ); if(requestType == 0) // Trivial sysMLrequests.append(trivialRequest2SysML(transindex, expr2SysML(minDelay), expr2SysML(maxDelay))); else if (requestType == 1) // Send sysMLrequests.append(sendRequest2SysML(transindex, expr2SysML(minDelay), expr2SysML(maxDelay), methodMap.get(((AvatarActionOnSignal)target).getSignal()), ((AvatarActionOnSignal)target).getValues())); else if (requestType == 2) // Receive sysMLrequests.append(receiveRequest2SysML(transindex, expr2SysML(minDelay), expr2SysML(maxDelay), methodMap.get(((AvatarActionOnSignal)target).getSignal()))); else if (requestType == 3) // Set sysMLrequests.append(setTimerRequest2SysML(transindex, expr2SysML(minDelay), expr2SysML(maxDelay), timerBlockSysMLname(((AvatarTimerOperator) target).getTimer().getName()) + ".'@set'", ((AvatarSetTimer) target).getTimerValue())); else if (requestType == 4) // Reset sysMLrequests.append(resetTimerRequest2SysML(transindex, expr2SysML(minDelay), expr2SysML(maxDelay), timerBlockSysMLname(((AvatarTimerOperator) target).getTimer().getName()) + ".'@reset'" )); else // Expire sysMLrequests.append(expireTimerRequest2SysML(transindex, expr2SysML(minDelay), expr2SysML(maxDelay), timerBlockSysMLname(((AvatarTimerOperator) target).getTimer().getName()) + ".'@expire'" )); if(guarded) { indent = indent.substring(indentStepSize); sysMLrequests.append("\n" + indent + "else '#nok_request'(" + transindex + ")"); } // computing transition indent = indent.substring(2 * indentStepSize); String doAction; indent += indentStep; if(requestType == 2) doAction = receiveActions2SysML(methodMap.get(((AvatarActionOnSignal)target).getSignal()), ((AvatarActionOnSignal)target).getValues()); else doAction = transitionActions2SysM(at.getActions()); indent = indent.substring(indentStepSize); sysMLtransitions.append("\n" + indent + "transition : '#AvatarTransition' first " + srcName); if(index > 0) sysMLtransitions.append(" if '@index' == " + index + "\n"); else sysMLtransitions.append("\n"); indent += indentStep; if (doAction.length() == 0) sysMLtransitions.append(indent + "then " + tgtName + endTransition(at.getDelayDistributionLaw(), at.getDelayExtra1(), at.getDelayExtra2(), at.getProbability())); else { sysMLtransitions.append(doAction); sysMLtransitions.append(" then " + tgtName + endTransition(at.getDelayDistributionLaw(),at.getDelayExtra1(),at.getDelayExtra2(), at.getProbability())); } indent += indentStep; } String trivialRequest2SysML(int index, String min, String max) { if (max.equals("0")) if (min.equals("0")) if (index == 1) return indent + "'#immediate_request'"; else return indent + "'#TrivialRequest'('@index' = " + index + ")"; else if (index == 1) return indent + "'#TrivialRequest'('@delay' = " + min + ")"; else return indent + "'#TrivialRequest'('@index' = " + index + ", '@delay' = " + min + ")"; else if (max.trim().equals(min.trim())) if(index == 1) return indent + "'#TrivialRequest'('@delay' = " + min + ")"; else return indent + "'#TrivialRequest'('@index' = " + index + ", '@delay' = " + min + ")"; else if(index == 1) return indent + "'#TrivialRequest'('@delay' = '#bound_random'(" + min + ", " + max + "))"; else return indent + "'#TrivialRequest'('@index' = " + index + ", '@delay' = '#bound_random'(" + min + ", " + max + "))"; } String sendRequest2SysML(int index, String min, String max, MethodInfo signalInfo, List<String> values) { StringBuffer result = new StringBuffer(indent + "'#SendRequest'(\n"); indent += indentStep; if (index != 1) result.append(indent + "'@index' = " + index + ",\n"); result.append(indent + "'@channel'= " + signalInfo.getName() + ",\n"); if (max.equals("0")) { if (!min.equals("0")) result.append(indent + "'@delay' = " + min + ",\n"); } else if (max.trim().equals(min.trim())) result.append(indent + "'@delay' = " + min + ",\n"); else result.append(indent + "'@delay' = '#bound_random'(" + min + ", " + max + "),\n"); int nbFields = signalInfo.getArity(); if (nbFields == 0) result.append(indent + "'@payload' = " + signalInfo.getMessageType() + "()\n"); else { result.append(indent + "'@payload' = " + signalInfo.getMessageType() + "(\n"); indent += indentStep; int j = 0; int k = 0; while (j < nbFields) { //for(String vl : values) if (signalInfo.getFieldType(j) != AvatarDataType.DATATYPE) { result.append(indent + expr2SysML(values.get(k)) + ",\n"); k++; j++; } else { AvatarDataType dt = signalInfo.getDataType(j); result.append(indent + expr2SysML(removeFieldName(values.get(k), dt)) + ",\n"); k += dt.getFullSize(); j++; } } result.replace(result.length()-2, result.length(), " )\n"); indent = indent.substring(indentStepSize); } indent = indent.substring(indentStepSize); result.append(indent + ")"); return result.toString(); } String setTimerRequest2SysML(int index, String min, String max, String chname, String value) { StringBuffer result = new StringBuffer(indent + "'#AvatarSetTimerRequest'(\n"); indent += indentStep; if (index != 1) result.append(indent + "'@index' = " + index + ",\n"); result.append(indent + "'@channel'= " + chname + ",\n"); if (max.equals("0")) { if (!min.equals("0")) result.append(indent + "'@delay' = " + min + ",\n"); } else if (max.trim().equals(min.trim())) result.append(indent + "'@delay' = " + min + ",\n"); else result.append(indent + "'@delay' = '#bound_random'(" + min + ", " + max + "),\n"); result.append(indent + "'@payload' = '#TimerSetMsg'(" + value + ")\n"); indent = indent.substring(indentStepSize); result.append(indent + ")"); return result.toString(); } String resetTimerRequest2SysML(int index, String min, String max, String chname) { StringBuffer result = new StringBuffer(indent + "'#AvatarResetTimerRequest'(\n"); indent += indentStep; if (index != 1) result.append(indent + "'@index' = " + index + ",\n"); result.append(indent + "'@channel'= " + chname + ",\n"); if (max.equals("0")) { if (!min.equals("0")) result.append(indent + "'@delay' = " + min + ",\n"); } else if (max.trim().equals(min.trim())) result.append(indent + "'@delay' = " + min + ",\n"); else result.append(indent + "'@delay' = '#bound_random'(" + min + ", " + max + "),\n"); result.append(indent + "'@payload' = '#TimerResetMsg'()\n"); indent = indent.substring(indentStepSize); result.append(indent + ")"); return result.toString(); } String receiveRequest2SysML(int index, String min, String max, MethodInfo chinfo) { StringBuffer result = new StringBuffer(indent + "'#ReceiveRequest'(\n"); indent += indentStep; if (index != 1) result.append(indent + "'@index' = " + index + ",\n"); result.append(indent + "'@channel'= " + chinfo.getName()); if (max.equals("0")) if (!min.equals("0")) result.append(",\n" + indent + "'@delay' = " + min + "\n"); else result.append("\n"); else if (max.trim().equals(min.trim())) result.append(indent + "'@delay' = " + min + ",\n"); else result.append(",\n" + indent + "'@delay' = '#bound_random'(" + min + ", " + max + ")\n"); indent = indent.substring(indentStepSize); result.append(indent + ")"); return result.toString(); } String expireTimerRequest2SysML(int index, String min, String max, String chname) { StringBuffer result = new StringBuffer(indent + "'#AvatarExpireTimerRequest'(\n"); indent += indentStep; if (index != 1) result.append(indent + "'@index' = " + index + ",\n"); result.append(indent + "'@channel'= " + chname); if (max.equals("0")) if (!min.equals("0")) result.append(",\n" + indent + "'@delay' = " + min + "\n"); else result.append("\n"); else if (max.trim().equals(min.trim())) result.append(indent + "'@delay' = " + min + ",\n"); else result.append(",\n" + indent + "'@delay' = '#bound_random'(" + min + ", " + max + ")\n"); indent = indent.substring(indentStepSize); result.append(indent + ")"); return result.toString(); } String methodCall2SysML(AvatarTermFunction m) { MethodInfo methodInfo = methodMap.get(m.getMethod()); List<AvatarTerm> parameters = m.getArgs().getComponents(); int nbFields = methodInfo.getArity(); if (nbFields == 0) return(methodInfo.getName() + "()"); StringBuffer result = new StringBuffer(methodInfo.getName() + "("); int j = 0; // index in method profile; int k = 0; // index in method parameters; while (j < nbFields) { if (methodInfo.getFieldType(j) != AvatarDataType.DATATYPE) { if (parameters.get(k) instanceof AvatarTermFunction) result.append(methodCall2SysML((AvatarTermFunction) parameters.get(k)) + ","); else result.append(expr2SysML(parameters.get(k).getName()) + ","); k++; j++; } else { AvatarDataType dt = methodInfo.getDataType(j); result.append(expr2SysML(removeFieldName(((AvatarAttribute) parameters.get(k)).getName(), dt)) + ","); k += dt.getFullSize(); j++; } } result.replace(result.length() - 1, result.length(), ")"); return result.toString(); } String transitionActions2SysM(List<AvatarAction> aas) { StringBuffer result; if (aas == null || aas.size() == 0) return ""; result = new StringBuffer(indent + "do action : '#TransitionAction' {\n" + indent + indentStep + "first start;\n"); indent += indentStep; for(AvatarAction aa : aas) { if(aa instanceof AvatarActionAssignment) { AvatarLeftHand lh = ((AvatarActionAssignment)aa).getLeftHand(); if(lh instanceof AvatarAttribute) result.append(indent + "then assign " + leftHandSysMLname(lh.getName()) + ":= "); else { // AvatarTuple of field-attributes result.append(indent + "then assign " + leftHandSysMLname(removeFieldName((AvatarAttribute)((AvatarTuple) lh).getComponents().get(0))) + ":= "); } AvatarTerm rh = ((AvatarActionAssignment)aa).getRightHand(); if (rh instanceof AvatarTuple) result.append( attributeSysMLname(removeFieldName((AvatarAttribute)((AvatarTuple) rh).getComponents().get(0))) + ";\n"); else if (rh instanceof AvatarTermFunction) result.append(methodCall2SysML((AvatarTermFunction)rh) + ";\n"); else result.append(expr2SysML(rh.getName()) + ";\n"); } else { result.append(indent + "then action = " + methodCall2SysML((AvatarTermFunction)aa) + ";\n"); } } result.append(indent + "then done;\n"); indent = indent.substring(indentStepSize); result.append(indent + "}"); return result.toString(); } String receiveActions2SysML(MethodInfo signalInfo, List<String> values) { if (values == null || values.size() == 0) return ""; StringBuffer result = new StringBuffer(indent + "do action : '#ReceiveAction' {\n"); indent += indentStep; result.append(indent + "item '@msg' : " + signalInfo.getMessageType() + " = '@payload' as " + signalInfo.getMessageType() + ";\n" + indent + "first start;\n"); int nbFields = signalInfo.getArity(); int j = 0; int k = 0; while (j < nbFields) { if (signalInfo.getFieldType(j) != AvatarDataType.DATATYPE) { result.append(indent + "then assign " + leftHandSysMLname(values.get(k)) + " := '@msg'." + signalInfo.getFieldName(j) + ";\n"); k++; j++; } else { AvatarDataType dt = signalInfo.getDataType(j); result.append(indent + "then assign " + leftHandSysMLname(removeFieldName(values.get(k), dt)) + " := '@msg'." + signalInfo.getFieldName(j) + ";\n"); k += dt.getFullSize(); j++; } } result.append(indent + "then done;\n"); indent = indent.substring(indentStepSize); result.append(indent + "}"); return result.toString(); } }