Newer
Older
value = receivePayload.get(aa.getName());
if (value == null) { // target variable undefined
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getLeft(),
"receiving transition has a missing field"));
value = "";
}
}
state.addOriginalValue(value);
// add basic primitive attributesextend value w.r.t
// extend value w.r.t its datatype if relevant
extendLocation = transition.getLeft();
String extendedPath = extendPath(value.replaceAll("\\.", "__"), blk);
if (extendedPath == null) { // value cannot be typed
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getLeft(), "attribute \"" +
value + "\" cannot be typed"));
// recover w.r.t expected type to continue while providing info
AvatarDataType adt = profile.get(k).getDataType();
if (adt == null) { // primitive type, keep target variable name as it is
ids = new String[1];
ids[0] = value;
} else { // datatype, extend target variable w.r.t datatype fields (although not well typed)
ids = extendName(value.replaceAll("\\.", "__"),adt).split(",");
}
}
else // value has a type (not verified: is it the expected type?)
ids = extendedPath.split(",");
// update state with (extended) value as target attribute (fields)
int isize = ids.length;
for (int w = 0; w < isize; w++) state.addValue(ids[w]);
}
}
else { // unrecoved error, skip transition
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getLeft(),
"receiving transition should lead to a receive state", transition.getRleft()));
// set-timer transitions =====================
else if (transition.getType() == AvatarFromSysMLSyntax.STXSETTIMERTRANSITION) {
if(tgtState instanceof AvatarSetTimer) {
AvatarSetTimer state = (AvatarSetTimer) tgtState;
// some unrecovered errors (transition skipped)
if (transition.getTimer() == null) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getLeft(),
"set-timer transition has no associated timer", transition.getRleft()));
AvatarAttribute tmr = getTimerByName(transition.getTimer(), theBlock);
if (tmr == null) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getTarget().getLeft(),
"timer of set-timer state does not exist", transition.getRleft()));
continue;
}
state.setTimer(tmr);
if (transition.getSendPayload() == null || transition.getSendPayload().size() != 1
|| !(transition.getSendPayload().get(0) instanceof StxExpr)) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, 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.ERROR, 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)
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getLeft(),
"reset-timer transition has no associated timer", transition.getRleft()));
// update target state with its specific parameter
AvatarAttribute tmr = getTimerByName(transition.getTimer(), theBlock);
if (tmr == null) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getTarget().getLeft(),
"timer of reset-timer state does not exist", transition.getRleft()));
continue;
}
state.setTimer(tmr);
else { // unrecoved error, skip transition
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, 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)
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getLeft(),
"expire-timer transition has no associated timer", transition.getRleft()));
// update target state with its specific parameter
AvatarAttribute tmr = getTimerByName(transition.getTimer(), theBlock);
if (tmr == null) {
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, transition.getTarget().getLeft(),
"timer of expire-timer state does not exist", transition.getRleft()));
continue;
}
state.setTimer(tmr);
state.setTimer(getTimerByName(transition.getTimer(), theBlock));
else { // unrecoved error, skip transition
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, 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.ERROR, 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.ERROR, "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.ERROR, "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.ERROR, "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.ERROR, _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.ERROR, _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.ERROR, _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.WARNING, _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);
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, ss.getLeft(),
// 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;
/** location for error messages while extending paths */
private Location extendLocation;
/** 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.
* If the path is irrelevant or leads to some undeclared datatype, returns "__undefined__path" or "__path__undefined_datatype_datatype"*/
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;
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, extendLocation,
"ident " + path + " is used but not declared in block " + b.getName()));
return "__undefined__" + path;
extendDataType = null;
extendPrimitiveType = AvatarType.INTEGER;
extendDataType = null;
extendPrimitiveType = AvatarType.BOOLEAN;
return path;
}
extendDataType = avSpec.getDataTypeByName(extendTypeString);
if (extendDataType != null)
return extendName(path, extendDataType);
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, extendLocation,
"ident " + path + " in block " + b.getName() + " has an unknown data type " + extendTypeString));
return "__" + path + "__undefined_datatype__" + extendTypeString;
/** 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.ERROR,
"relation " + r.getName() + " has been used but has not been declared"));
}
// check size
int size = r.getSize();
if (size == 0) { // empty relation is droped
addError(new AvatarFromSysMLError(AvatarFromSysMLError.WARNING, r.getLeft(),
"relation is empty"));
}
int i = 0;
if (r.getBlock1() == null || r.getBlock2() == null) { // AvatarBlock structures not found
while (i < size && (r.getChannel(i).getBlockA() == null || r.getChannel(i).getBlockB() == null)) i++;
if (i == size){
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR,
"blocs of relation " + r.getName() + " unspecified, recovery from channels failed"));
}
else
addError(new AvatarFromSysMLError(AvatarFromSysMLError.WARNING,
"blocs of relation " + r.getName() + " unspecified, recovered from channel " + r.getChannel(i).getName()));
r.setBlock1(stxSpec.getBlockMap().get(r.getChannel(i).getBlockA()));
r.setBlock2(stxSpec.getBlockMap().get(r.getChannel(i).getBlockB()));
// 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());
for (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
if(c.getBlockA() == null || c.getBlockA() == null)
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, c.getLeft(),
"missing associated block to channel " + c.getName()));
else
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, c.getLeft(),
"inconsistency between blocs of channel " + c.getName() + " and its relation " + r.getName()));
if (c.getSignalA() != null && c.getSignalB() != null)
theRelation.addSignals(getSignal(c.getSignalA()),getSignal(c.getSignalB()));
else
addError(new AvatarFromSysMLError(AvatarFromSysMLError.ERROR, c.getLeft(),
"missing signal binding for channel" + c.getName()));