Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* 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
*/
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
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
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) {
}
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>();
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() {
if (size < 2) return;
StringBuffer chain = new StringBuffer(indentStep + "part " + blockChain.get(size - 1) + " = ");
for (int i=0; i < size-1; i++){
chain.append(blockChain.get(i) + ".");
}
chain.append(blockChain.get(size - 1) + ";\n");
blockLinks.append(chain);
}
StringBuffer blockLinks = new StringBuffer();
String indentStep = " ";
int indentStepSize = 4;
String indent = "";
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 AvatarCommunication::*;\n";
blockLinks = new StringBuffer(indentStep + "// Block Shortcut Links $$$$$$$$$$$$\n");
searchCountSignals();;
dataTypes2SysML();
avsysml.append("}\n");
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);
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() + ")";
relationParameters += ", 'private'=true, lossy=true)";
relationParameters += ", 'private'=true, max_size=" + ar.getSizeOfFIFO() + ")";
relationParameters += ", 'private'=true)";
else
if(ar.isLossy()) // default: false
if(ar.getSizeOfFIFO() > 1) // default size: 1
relationParameters += ", lossy=true, max_size=" + ar.getSizeOfFIFO() + ")";
relationParameters += ", lossy=true)";
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);
avsysml.append("\n" + indent + "// Channel " + channelSYSMLname + "-------------\n");
avsysml.append(indent + "part " + channelSYSMLname + " : " + channelConstructor + " = "
+ channelConstructor + "(relation = " + relationSYSMLname + ");\n");
if (in2out) {
avsysml.append(indent + "bind " + blk1SysMLname + "." + sig1SYSMLname + " = " + channelSYSMLname + "{ attribute isIn : " +
"Boolean = true; }\n");
avsysml.append(indent + "bind " + blk2SysMLname + "." + sig2SYSMLname + " = " + channelSYSMLname + "{ attribute isIn : " +
"Boolean = false; }\n");
} else {
avsysml.append(indent + "bind " + blk1SysMLname + "." + sig1SYSMLname + " = " + channelSYSMLname + "{ attribute isIn : " +
"Boolean = false; }\n");
avsysml.append(indent + "bind " + blk2SysMLname + "." + sig2SYSMLname + " = " + channelSYSMLname + "{ attribute isIn : " +
"Boolean = true; }\n");
}
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 " + message2SYSMLname + " :> '#DataMessage' {\n" +
indent + indentStep + "private part '@channel' : '#Channel' = " + channelSYSMLname + ";\n");
msg2Buf.append(indent + "part def " + message1SYSMLname + " :> " + message2SYSMLname + "{\n");
} else {
msg1Buf.append(indent + "part def " + message1SYSMLname + " :> '#DataMessage' {\n" +
indent + indentStep + "private part '@channel' : '#Channel' = " + channelSYSMLname + ";\n");
msg2Buf.append(indent + "part def " + message2SYSMLname + " :> " + message1SYSMLname + "{\n");
}
// 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 " + fieldName2 + " : " + attributeType);
msg2Buf.append(indent + "attribute " + fieldName1 + " redefines " + fieldName2 + ";\n");
} else {
msg1Buf.append(indent + "attribute " + fieldName1 + " : " + attributeType);
msg2Buf.append(indent + "attribute " + fieldName2 + " redefines " + fieldName1 + ";\n");
}
sig1Info.addField(fieldName1, type, dataType);
sig2Info.addField(fieldName2, type, dataType);
msg1Buf.append(indent + "}\n");
msg2Buf.append(indent + "}\n");
avsysml.append(msg1Buf);
avsysml.append(msg2Buf);
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()));
}
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);
}
avsysml.append(indent + "action " + methodSysMLname(am.getName()) + ": '#AvatarVoidMethod' {\n");
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);
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());
chainBlock(blockSYSMLname);
blocklink();
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();
}
}
}
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);
}
avsysml.append("\n" + indent + "// state-machine -------------------\n");
if (timerList != null && timerList.size() != 0) {
avsysml.append("\n" + indent + "// Timers ---------------------\n");
for (AvatarAttribute timer : timerList) timer2SysML(timer);
}
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);
}
avsysml.append("\n" + indent + "// BLOCKS $$$$$$$$$$$$$$$$$$$$$$$$\n");
for(AvatarBlock block: avspec.getListOfBlocks())
if (block.getFather() == null) block2SysML(block);
}
void timer2SysML(AvatarAttribute timer) {
String relationname = timerRelationSysMLname(timer.getName());
String settimername = setTimerChannelSysMLname(timer.getName());
String resettimername = resetTimerChannelSysMLname(timer.getName());
String expiretimername = expireTimerChannelSysMLname(timer.getName());
String timerblockname = timerBlockSysMLname(timer.getName());
avsysml.append(indent + "part " + relationname + ": '#Timer_Rel';\n");
avsysml.append(indent + "part " + settimername + ": '#Sync' = '#Sync'(relation = " + relationname + ");\n");
avsysml.append(indent + "part " + resettimername + ": '#Sync' = '#Sync'(relation = " + relationname + ");\n");
avsysml.append(indent + "part " + expiretimername + ": '#Sync' = '#Sync'(relation = " + relationname + ");\n");
avsysml.append(indent + "part " + timerblockname + ": '#AvatarTimer';\n");
avsysml.append(indent + "bind " + timerblockname + ".set = " + settimername + ";\n");
avsysml.append(indent + "bind " + timerblockname + ".reset = " + resettimername + ";\n");
avsysml.append(indent + "bind " + timerblockname + ".expire = " + expiretimername + ";\n");
Boolean stopState;
// 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(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++));
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++));
}
stateinfo = new StateInfo(countStateSysMLname(((AvatarQueryOnSignal)asme).getSignal().getName(), countNumber++));
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);
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'");
avsysml.append(";\n");
avsysml.append(" = '#AvatarStandardState'(\n" + requests + "\n" + indent + ");\n");
avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarRandomState' = '#AvatarRandomState'(\n");
if (!requests.equals("")) avsysml.append(requests + ",\n");
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");
avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarCountState' = '#AvatarCountState'(\n");
if (!requests.equals("")) avsysml.append(requests + ",\n");
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'");
avsysml.append(";\n");
avsysml.append(" = '#AvatarSendState'(\n" + requests + "\n" +indent + ");\n");
avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarReceiveState'");
avsysml.append(";\n");
avsysml.append(" = '#AvatarReceiveState'(\n" + requests + "\n" + indent + ");\n");
}
} else
if(asme instanceof AvatarStartState){
avsysml.append("\n" + indent + "entry action " + stateMap.get(asme).getName() + " :'#AvatarStartState'");
avsysml.append(";\n");
avsysml.append(" = '#AvatarStartState'(\n" + requests + "\n" + indent + ");\n");
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'");
avsysml.append(";\n");
avsysml.append(" = '#AvatarSetTimerState'(\n" + requests + "\n" + indent + ");\n");
} else
if(asme instanceof AvatarResetTimer){
avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarResetTimerState'");
avsysml.append(";\n");
avsysml.append(" = '#AvatarResetTimerState'(\n" + requests + "\n" + indent + ");\n");
} else
if(asme instanceof AvatarExpireTimer){
avsysml.append("\n" + indent + "state " + stateMap.get(asme).getName() + " : '#AvatarExpireTimerState'");
avsysml.append(";\n");
avsysml.append(" = '#AvatarExpireTimerState'(\n" + requests + "\n" + indent + ");\n");
}
// Transition descriptions
avsysml.append(sysMLtransitions);
// PreComm States and their outgoing transition
for (AvatarStateMachineElement aos: requirePreCom) {
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");
avsysml.append("\n" + indent + "transition : '#AvatarTransition' first " + stateinfo.getPreName() +
" then " + stateinfo.getName() +
endTransition(0,"","", 1));
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");
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));
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",
setTimerChannelSysMLname(((AvatarSetTimer) aos).getTimer().getName()),
((AvatarSetTimer)aos).getTimerValue()) + "\n");
indent = indent.substring(2 * indentStepSize);
avsysml.append(indent + ");\n");
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",
resetTimerChannelSysMLname(((AvatarResetTimer) aos).getTimer().getName())) + "\n");
indent = indent.substring(2 * indentStepSize);
avsysml.append(indent + ");\n");
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",
expireTimerChannelSysMLname(((AvatarExpireTimer) aos).getTimer().getName())) + "\n");
indent = indent.substring(2 * indentStepSize);
avsysml.append(indent + ");\n");
avsysml.append("\n" + indent + "transition : '#AvatarTransition' first " + stateinfo.getPreName() +
endTransition(0,"","", 1));
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) {
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");
}
// 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);
}
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()),
else if (requestType == 2) // Receive
expr2SysML(minDelay),
expr2SysML(maxDelay),
methodMap.get(((AvatarActionOnSignal)target).getSignal())));
else if (requestType == 3) // Set
sysMLrequests.append(setTimerRequest2SysML(transindex,
expr2SysML(minDelay),
expr2SysML(maxDelay),
setTimerChannelSysMLname(((AvatarTimerOperator) target).getTimer().getName()),
((AvatarSetTimer) target).getTimerValue()));
else if (requestType == 4) // Reset
sysMLrequests.append(resetTimerRequest2SysML(transindex,
expr2SysML(minDelay),
expr2SysML(maxDelay),
resetTimerChannelSysMLname(((AvatarTimerOperator) target).getTimer().getName())));
else // Expire
sysMLrequests.append(expireTimerRequest2SysML(transindex,
expr2SysML(minDelay),
expr2SysML(maxDelay),
expireTimerChannelSysMLname(((AvatarTimerOperator) target).getTimer().getName())));
if(guarded) {
indent = indent.substring(indentStepSize);
sysMLrequests.append("\n" + indent + "else '#nok_request'(" + transindex + ")");
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 response.transition_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()));
sysMLtransitions.append(" then " + tgtName +
endTransition(at.getDelayDistributionLaw(),at.getDelayExtra1(),at.getDelayExtra2(), at.getProbability()));
}
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'(transition_index= " + index + ")";
else
if (index == 1)
return indent + "'#TrivialRequest'(delay= " + min + ")";
else
return indent + "'#TrivialRequest'(transition_index= " + index + ", delay= " + min + ")";
else if (max.trim().equals(min.trim()))
if(index == 1)
return indent + "'#TrivialRequest'(delay= " + min + ")";
else
return indent + "'#TrivialRequest'(transition_index= " + index + ", delay= " + min + ")";
else
if(index == 1)
return indent + "'#TrivialRequest'(delay= '#bound_random'(" + min + ", " + max + "))";
else
return indent + "'#TrivialRequest'(transition_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");
if (index != 1)
result.append(indent + "transition_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");