Newer
Older
AvatarSetTimer state = (AvatarSetTimer) tgtState;
// some unrecovered errors (transition skipped)
if (transition.getTimer() == null) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, transition.getLeft(),
"set-timer transition has no associated timer", transition.getRleft()));
}
state.setTimer(getTimerByName(transition.getTimer(), theBlock));
if (transition.getSendPayload() == null || transition.getSendPayload().size() != 1
|| !(transition.getSendPayload().get(0) instanceof StxExpr)) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, transition.getLeft(),
"payload of set-timer transition is not well formed", transition.getRleft()));
continue;
}
// update target state with its specific parameters
state.setTimerValue(((StxExpr)transition.getSendPayload().get(0)).toString().replaceAll(".","__"));
state.setTimerOriginalValue(((StxExpr)transition.getSendPayload().get(0)).toString());
}
else { // unrecoved error, skip transition
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, transition.getLeft(),
"set-timer transition should lead to a set-timer state", transition.getRleft()));
continue;
}
// reset-timer transitions =====================
else if (transition.getType() == AvatarFromSysMLSyntax.STXRESETTIMERTRANSITION) {
if(tgtState instanceof AvatarResetTimer) {
AvatarResetTimer state = (AvatarResetTimer) tgtState;
// an unrecovered error (transition skipped)
if (transition.getTimer() == null) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, transition.getLeft(),
"reset-timer transition has no associated timer", transition.getRleft()));
// update target state with its specific parameter
state.setTimer(getTimerByName(transition.getTimer(), theBlock));
}
else { // unrecoved error, skip transition
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, transition.getLeft(),
"reset-timer transition should lead to a reset-timer state", transition.getRleft()));
continue;
}
// expire-timer transitions =====================
else if (transition.getType() == AvatarFromSysMLSyntax.STXEXPIRETIMERTRANSITION) {
if(tgtState instanceof AvatarExpireTimer) {
AvatarExpireTimer state = (AvatarExpireTimer) tgtState;
// an unrecovered error (transition skipped)
if (transition.getTimer() == null) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, transition.getLeft(),
"expire-timer transition has no associated timer", transition.getRleft()));
// update target state with its specific parameter
state.setTimer(getTimerByName(transition.getTimer(), theBlock));
else { // unrecoved error, skip transition
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, transition.getLeft(),
"expire-timer transition should lead to a expire-timer state", transition.getRleft()));
continue;
}
// standard transitions to non-communicating state =====================
else if (! (tgtType == AvatarFromSysMLSyntax.STXSTOPSTATE ||
tgtType == AvatarFromSysMLSyntax.STXSTANDARDSTATE ||
tgtType == AvatarFromSysMLSyntax.STXRANDOMSTATE ||
tgtType == AvatarFromSysMLSyntax.STXCOUNTSTATE ||
tgtType == AvatarFromSysMLSyntax.STXSTARTSTATE) ) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, transition.getLeft(),
"transition type is not consistant with the type of its target state", transition.getTarget().getLeft()));
// All unrecovered errors have been avoided, the transition can be added
asm.addElement(theTransition);
theSourceState.addNext(theTransition);
addTransition(theTransition, tgtState); // memorize incoming transition for post-processing
// post-processing: verify some constraints on incoming transitions
transitionMap.forEach(new CheckIncommings());
}
}
/** makes some verifications relative to incomming edges, not all. In particular, not all unreachable states are removed, but this must ensure at
* least that keeped states are sufficiently well defined to be handled by the graphic representation building process (avoiding crashes) */
private class CheckIncommings implements BiConsumer<AvatarStateMachineElement, StateTransitions> {
List<AvatarDataType> dataTypeList;
public CheckIncommings(){}
public void accept(AvatarStateMachineElement e, StateTransitions st) {
int s = st.getTransitions().size();
if (s == 0 && ! (e instanceof AvatarStartState)) { // unreachable state that may be not well defined => to remove
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWERROR, "state " + e.getName() +
" of block " + st.getBlock().getName() + " is unreachable --> removed"));
st.getBlock().getStateMachine().removeElement(e);
for(AvatarStateMachineElement x : e.getNexts())
st.getBlock().getStateMachine().removeElement(x);
if (s > 0 && (e instanceof AvatarStartState)) { // start state has input edges => redirected to error stopstate
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWERROR, "start state in bloc " +
st.getBlock().getName() + " has some input transition"));
for(int i = 0; i < s; i++) {
st.getTransitions().get(i).getNexts().clear();
AvatarStopState nw = new AvatarStopState("errorstate",null, st.getBlock());
st.getTransitions().get(i).addNext(nw);
st.getBlock().getStateMachine().addElement(nw);
if (s > 1 && !(e instanceof AvatarStartState || e instanceof AvatarStateElement)) { // too much input edges => redirected to error stopstate
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWERROR, "state " + e.getName() + " in bloc " +
st.getBlock().getName() + " has more than one incomming transition"));
for(int i = 1; i < s; i++) {
st.getTransitions().get(i).getNexts().clear();
AvatarStopState nw = new AvatarStopState("errorstate",null, st.getBlock());
st.getTransitions().get(i).addNext(nw);
st.getBlock().getStateMachine().addElement(nw);
/** create-and-add AvatarBlocks. successive calls of BuildBlock and BuildStateMachine for each syntactic block */
private void buildBlocks(){
stxSpec.getBlockMap().forEach(new BuildBlock());
stxSpec.getBlockMap().forEach(new BuildStateMachine());
/** complete the parameter transition with distribution law information provided in other parameters.
*
* @param _t the transition to provide with distribution law information
* @param distributionLaw the distribution law name
* @param delayExtra a map of distribution law parameters to values
* @param _st the syntactic transition (provides locations for error messages)
*/
private void setDistributionLaw(AvatarTransition _t, String distributionLaw, HashMap<String,String> delayExtra, StxTransition _st) {
int law = -1;
int size;
// identify distribution law......... set default DELAY_UNIFORM_LAW when a problem is encountered
if (distributionLaw == null || distributionLaw.equals("")) law = DELAY_UNIFORM_LAW;
else {
size = DISTRIBUTION_LAWS.length;
for (int i = 0; i < size; i++) { // search in defined laws
if (DISTRIBUTION_LAWS[i].equals(distributionLaw)) {
law = i;
break;
}
}
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, _st.getLeft(),
"transition with unknown transition law : " + distributionLaw + " (set to uniform)"));
// try to get law parameters............
// get law parameter names
String extra1 = LABELS_OF_EXTRA_ATTRIBUTES_1[law];
String extra2 = LABELS_OF_EXTRA_ATTRIBUTES_2[law];
size = NB_OF_EXTRA_ATTRIBUTES[law];
int max = size;
if (size > 0) {
extra1 = delayExtra.get(extra1); // try to get value of first parameter through its name
if (extra1 == null) { // not found
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWERROR, _st.getLeft(),
"transition law : " + distributionLaw + " requires a " + tmpString + " parameter"));
if (size > 1) {
extra2 = delayExtra.get(extra2); // try to get value of second parameter through its name
if (extra2 == null) { // not found
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWERROR, _st.getLeft(),
"transition law : " + distributionLaw + " requires a " + tmpString + " parameter"));
}
}
if (delayExtra != null && delayExtra.size() > max) { // there is some unexpected parameter value
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWWARNING, _st.getLeft(),
"transition law : " + distributionLaw + " has irrelevant parameters"));
_t.setDistributionLaw(law, extra1, extra2);
}
/** fills the parameters of a method (or signal) w.r.t. the data of a syntactic structure
*
* @param ss the syntactic structure containing field information
* @param am the method to update by adding the fields characterized in ss
* @param b the block of the method
*/
private void buildProfile(StxStructure ss, AvatarMethod am, AvatarBlock b) {
AvatarAttribute aa;
int size = ss.getSize();
for (int i = 0; i < size; i++) { // iterates on the fields of the structure ss
String type = ss.getFieldType(i);
if (type.equals("Integer")){
aa = new AvatarAttribute(ss.getFieldName(i), AvatarType.INTEGER, b, null);
aa.setAsConstant(false);
aa = new AvatarAttribute(ss.getFieldName(i), AvatarType.INTEGER, b, null);
am.addParameter(aa);
aa.setAsConstant(false);
} else if (type.equals("Boolean")) {
aa = new AvatarAttribute(ss.getFieldName(i), AvatarType.BOOLEAN, b, null);
aa.setAsConstant(false);
aa = new AvatarAttribute(ss.getFieldName(i), AvatarType.BOOLEAN, b, null);
am.addParameter(aa);
aa.setAsConstant(false);
if (adt == null) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWWARNING, ss.getLeft(),
"message profile uses undefined datatype " + type));
// add the original version of the field to am
String aaName = ss.getFieldName(i);
aa = new AvatarAttribute(aaName, AvatarType.UNDEFINED, b, null);
aa.setDataType(adt);
am.addOriginalParameter(aa);
aa.setAsConstant(false);
// add the primitive basic attributes corresponding to the datatype's field
if (adt != null) {
aaName = aaName + "__";
AvatarDataTypePrimitiveFields primitiveFields = primitiveFieldsMap.get(adt);
int dtsize = primitiveFields.size();
for (int j = 0; j < dtsize; j++) {
aa = new AvatarAttribute(aaName + primitiveFields.getName(j),
primitiveFields.getType(j), b, null);
am.addParameter(aa);
aa.setAsConstant(false);
}
} else { // error, try to continue with the non coherent attribute alone
aa = new AvatarAttribute(aaName, AvatarType.UNDEFINED, b, null);
am.addParameter(aa);
aa.setAsConstant(false);
}
}
/** get the type of an attribute (not an attribute field) from a syntactic block */
private String getStxAttributeType(String name, StxBlock blk){
int size = blk.getNbAttributes();
for (int i = 0; i < size; i++) {
if (blk.getAttribute(i).getName().equals(name)) return blk.getAttribute(i).getType();
}
return null;
}
/** get the type of an attribute (or an attribute field, with "__" as field delimiter) from a syntactic block */
private String getStxPathType(String s, StxBlock b) {
String[] path = s.split("__");
String type = getStxAttributeType(path[0], b);
int size = path.length;
for (int i = 1; i < size; i++) {
if (adt == null) return null;
int nbFields = adt.attributeNb();
int j;
for (j = 0; j < nbFields; j++)
if (adt.getAttribute(j).getName().equals(path[i])) break;
if (j == nbFields) return null;
AvatarType adtType = adt.getAttribute(j).getType();
if (adtType == AvatarType.INTEGER)
type = "Boolean";
else
type = adt.getAttribute(j).getDataType().getName();
}
return type;
}
/** (string) Type found for ident extended by by extendPath (and thus extendIdent) */
private String extendTypeString;
/** DataType found for ident extended by extendPath (and thus extendIdent) if not primitive type */
private AvatarDataType extendDataType;
/** Primitive type found for ident extended by extendPath (and thus extendIdent) if not datatype type */
private AvatarType extendPrimitiveType;
/** extends a parameter attribute or field name x in a list "x__field1, ..., x__fieldN" respecting the fields of its associated type.
* If type is primitive, returns x unchanged. Updates extendTypeString, extendDataType and extendPrimitiveType w.r.t. the found type. */
private String extendPath(String path, StxBlock b) {
extendTypeString = getStxPathType(path, b);
if (extendTypeString == null) { // path cannot be typed, return null to notify the error
extendDataType = null;
extendPrimitiveType = null;
return null;
}
extendDataType = null;
extendPrimitiveType = AvatarType.INTEGER;
extendDataType = null;
extendPrimitiveType = AvatarType.BOOLEAN;
return path;
}
extendDataType = avSpec.getDataTypeByName(extendTypeString);
if (extendDataType != null)
return extendName(path, extendDataType);
else return null;
}
/** extends a parameter name x in a list "x__field1, ..., x__fieldN" respecting the fields of parameter datatype */
private String extendName(String name, AvatarDataType adt) {
if (adt != null) {
AvatarDataTypePrimitiveFields primitiveFields = primitiveFieldsMap.get(adt);
StringBuffer res = new StringBuffer();
int i;
for (i = 0; i < size; i++)
res.append(name + "__" + primitiveFields.getName(i) + ", ");
res.append(name + "__" + primitiveFields.getName(i));
return res.toString();
}
else return null;
/** extends a parameter attribute or field name x in a list in brackets "(x__field1, ..., x__fieldN)" respecting the fields of its associated
* type. If this type is primitive, returns x unchanged. Updates extendTypeString, extendDataType and extendPrimitiveType w.r.t. the found type.
* extends a parameter name x in a list "x__field1, ..., x__fieldN" respecting the fields of parameter datatype
*/
private String extendIdent (String path, StxBlock b) {
String result = extendPath(path, b);
return (result.indexOf(',') == -1 ? result : "(" + result + ")");
}
/** builds the string associated to a method call while extending the ones among the idents it uses that are datatype-typed */
private String extendCall (StxCall call, StxBlock b) {
StringBuffer result = new StringBuffer();
int size = call.getNbIdents();
int i;
for (i =0 ; i < size; i++) {
result.append(call.getSegment(i));
result.append(extendPath(call.getIdent(i).replaceAll("\\.", "__"), b));
}
result.append(call.getSegment(i));
return result.toString().replaceAll("\\.", "__");
}
/** rebuilds the original string associated to a method call, without ident extension */
private String extendOriginalCall (StxCall call, StxBlock b) {
StringBuffer result = new StringBuffer();
int size = call.getNbIdents();
int i;
for (i =0 ; i < size; i++) {
result.append(call.getSegment(i));
}
result.append(call.getSegment(i));
return result.toString();
}
// BUILD RELATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/** create-and-add-to-avSpec the relations identified in stxSpec */
private void buildRelations(){
stxSpec.getRelationMap().forEach(new BuildRelation());
}
/** to be run on relations identified while parsing and memorized in stxSpec's relation map. Create, fill and adds-to-avSpec a relation. */
private class BuildRelation implements BiConsumer<String, StxRelation> {
public BuildRelation() {
}
public void accept(String n, StxRelation r) {
if (!r.isDeclared()) { // declaration part is missing in source
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWERROR,
"relation " + r.getName() +" has been used but has not been declared"));
if (size == 0) { // empty relation is droped
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWWARNING, r.getLeft(),
"relation is empty"));
return;
} else { // channels found, try to recover blocks from them
int i = 0;
while (i < size && (r.getChannel(i).getBlockA() == null || r.getChannel(i).getBlockB() == null)) i++;
if (i == size) { // cannot find a channel with two clearly named blocks, drop relation
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR,
"cannot determine blocs of relation " + r.getName()));
return;
}
// block names found, search associated AvatarBlock structures
r.setBlock1(stxSpec.getBlockMap().get(r.getChannel(i).getBlockA()));
r.setBlock2(stxSpec.getBlockMap().get(r.getChannel(i).getBlockB()));
if (r.getBlock1() == null || r.getBlock2() == null) { // AvatarBlock structures not found, drop relation
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR,
"cannot determine blocs of relation " + r.getName()));
return;
}
}
}
// from here, relation has blocks (from declaration or recovered)
AvatarBlock blk1 = getBlock(r.getBlock1());
AvatarBlock blk2 = getBlock(r.getBlock2());
// create-and-add-to-avSpec the Avatar relation
AvatarRelation theRelation = new AvatarRelation(n, blk1, blk2, null);
avSpec.addRelation(theRelation);
theRelation.setAsynchronous(r.getAsynchronous());
theRelation.setPrivate(r.getPrivate());
theRelation.setLossy(r.getLossy());
theRelation.setBlocking(r.getBlocking());
theRelation.setSizeOfFIFO(r.getFifoSize());
if (size == 0) { // empty relation, kept because coherent although useless
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWWARNING, r.getLeft(),
for (int i = 0; i < size; i++) { // iterate on channels
StxChannel c = r.getChannel(i); // get channel
c.commuteSignals(r.getBlock1().getName()); // make channel respect block order in relation
if (!blk1.getName().equals(c.getBlockA()) || !blk2.getName().equals(c.getBlockB())) { // channel doesn't respect relation's blocks
addError(new AvatarFromSysMLError(AvatarFromSysMLError.HIGHERROR, c.getLeft(),
"inconsistency between blocs of channel " + c.getName() + " and its relation " + r.getName()));
continue;
if (c.getSignalA() != null && c.getSignalB() != null)
theRelation.addSignals(getSignal(c.getSignalA()),getSignal(c.getSignalB()));
else
addError(new AvatarFromSysMLError(AvatarFromSysMLError.LOWERROR, c.getLeft(),
"missing signal binding for channel"));
}