Skip to content
Snippets Groups Projects
AvatarSpecification.java 62.7 KiB
Newer Older
/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille
 * 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.
 */

Sophie Coudert's avatar
Sophie Coudert committed
import avatartranslator.tosysmlv2.*;
Sophie Coudert's avatar
Sophie Coudert committed
import avatartranslator.intboolsolver.AvatarIBSolver;
import myutil.Conversion;
import myutil.intboolsolver.IBSParamSpec;
import org.apache.derby.iapi.types.DataType;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
 * Class AvatarSpecification
 * Avatar specification
 * Creation: 20/05/2010
 *
 * @author Ludovic APVRILLE
 * @version 1.0 20/05/2010
public class AvatarSpecification extends AvatarElement implements IBSParamSpec {
    private static String keywords[] = {"BOOL", "INT", "TIMER", "SIGNAL", "METHOD", "STATE", "BLOCK", "CLASS"};

Ludovic Apvrille's avatar
Ludovic Apvrille committed
    public final static int UPPAAL_MAX_INT = 32767;

    public static String[] ops = {">", "<", "+", "-", "*", "/", "[", "]", "(", ")", ":", "=", "==", ",", "!", "?", "{", "}", "|", "&"};
    private final List<AvatarBlock> blocks;
    private final List<AvatarRelation> relations;
    private final List<AvatarAMSInterface> interfaces;
    private final List<AvatarDataType> dataTypes;

    /**
     * The list of all library functions that can be called.
     */
    private final List<AvatarLibraryFunction> libraryFunctions;
    private final List<AvatarPragma> pragmas; // Security pragmas
    private final List<String> safetyPragmas;
    private final HashMap<String, String> safetyPragmasRefs;
    private final List<AvatarPragmaLatency> latencyPragmas;
    private final List<AvatarConstant> constants;
    private final boolean robustnessMade = false;
    public List<String> checkedIDs;
    private List<AvatarInterfaceRelation> irelations;
    //private AvatarBroadcast broadcast;
    private String applicationCode;
    private Object informationSource; // Element from which the spec has been built
    // For JSON return
    private static ArrayList<String> jsonErrors;


    public AvatarSpecification(String _name, Object _referenceObject) {
        super(_name, _referenceObject);
        blocks = new LinkedList<>();
        interfaces = new LinkedList<>();
        relations = new LinkedList<>();
        dataTypes = new LinkedList<>();
        pragmas = new LinkedList<>();
        constants = new LinkedList<>();
        safetyPragmas = new LinkedList<>();
        safetyPragmasRefs = new HashMap<>();
        latencyPragmas = new LinkedList<>();
        this.constants.add(AvatarConstant.FALSE);
        this.constants.add(AvatarConstant.TRUE);
        checkedIDs = new ArrayList<>();
        this.libraryFunctions = new LinkedList<>();
    }

    public AvatarRelation getAvatarRelationWithBlocks(AvatarBlock block1, AvatarBlock block2, boolean synchronous) {
        for (AvatarRelation rel : relations) {
            if ((block1 == rel.block1) || (block1 == rel.block2)) {
                if ((block2 == rel.block1) || (block2 == rel.block2)) {
                    if (rel.isAsynchronous() == !synchronous) {
                        return rel;
                    }
                }
    public void removeAnomalies(){
        // Rename signals with the same name going from one block to the same block
        // Rename it by adding "in_" at the beginning

        for(AvatarRelation ar: relations) {
            if (ar.block1 == ar.block2) {
                for(int i=0; i<ar.nbOfSignals(); i++) {
                    AvatarSignal sig1 = ar.getSignal1(i);
                    AvatarSignal sig2 = ar.getSignal2(i);

                    if (sig1.getName().compareTo(sig2.getName()) == 0) {
                        // One of the two must be renamed. We rename the out signal
                        String name;
                        if (sig1.isOut()) {
                            name = ar.block1.findUniqueSignalName("out_" + sig1.getName());
                            sig1.setName(name);
                        } else {
                            name = ar.block2.findUniqueSignalName("out_" + sig2.getName());
                            sig2.setName(name);
                        }
                    }
                }
            }
        }

    }


    public static AvatarSpecification fromJSON(String _spec, String _name, Object _referenceObject, boolean tryToCorrectErrors) {
        if (_spec == null) {
            return null;
        }


        AvatarSpecification spec = new AvatarSpecification(_name, _referenceObject);
        jsonErrors = new ArrayList<>();

        int indexStart = _spec.indexOf('{');
        int indexStop = _spec.lastIndexOf('}');

        if ((indexStart == -1) || (indexStop == -1) || (indexStart > indexStop)) {
            throw new org.json.JSONException("Invalid JSON object (start)");
        }

        _spec = _spec.substring(indexStart, indexStop + 1);

Ludovic Apvrille's avatar
Ludovic Apvrille committed
        //TraceManager.addDev("Cut spec: " + _spec);

        JSONObject mainObject = new JSONObject(_spec);

        JSONArray blocksA = mainObject.getJSONArray("blocks");

        if (blocksA == null) {
            TraceManager.addDev("No blocks in json");
            return spec;
        }

        for (int i = 0; i < blocksA.length(); i++) {
            JSONObject blockO = blocksA.getJSONObject(i);
            String name = spec.removeSpaces(blockO.getString("name"));
            if (name != null) {
                AvatarBlock newBlock = new AvatarBlock(name, spec, _referenceObject);
                spec.addBlock(newBlock);

                try {
                    JSONArray attributesA = blockO.getJSONArray("attributes");
                    if (attributesA != null) {
                        for (int j = 0; j < attributesA.length(); j++) {
                            String nameA = spec.removeSpaces(attributesA.getJSONObject(j).getString("name"));
                            String typeA = attributesA.getJSONObject(j).getString("type");
                            AvatarType at = AvatarType.getType(typeA);

                            if (at == AvatarType.UNDEFINED) {
                                jsonErrors.add("In block " + newBlock.getName() + " attribute " + nameA + " is invalid because " +
                                        "\"" + typeA + "\"is an invalid type (only int or bool).");
                            }

                            if (tryToCorrectErrors) {
                                if (at != AvatarType.UNDEFINED) {
                                    AvatarAttribute aa = new AvatarAttribute(nameA, at, newBlock, _referenceObject);
                                    newBlock.addAttribute(aa);
                                } else {
                                    AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.INTEGER, newBlock, _referenceObject);
                                    newBlock.addAttribute(aa);
                                }
                            } else {
                                AvatarAttribute aa = new AvatarAttribute(nameA, at, newBlock, _referenceObject);
                                newBlock.addAttribute(aa);
                            }
                    }
                } catch (JSONException je) {
                }

                try {
                    JSONArray methodsA = blockO.getJSONArray("methods");
                    for (int j = 0; j < methodsA.length(); j++) {
                        String nameM = spec.removeSpaces(methodsA.getJSONObject(j).getString("name"));
                        AvatarMethod am = new AvatarMethod(nameM, _referenceObject);
                        JSONArray params = methodsA.getJSONObject(j).getJSONArray("parameters");
                        for (int k = 0; k < params.length(); k++) {
                            String nameA = spec.removeSpaces(params.getJSONObject(k).getString("name"));
                            String typeA = params.getJSONObject(k).getString("type");
                            AvatarType at = AvatarType.getType(typeA);
                            if (at == AvatarType.UNDEFINED) {
                                jsonErrors.add("In block " + newBlock.getName() + " attribute " + nameA + " is invalid because " +
                                        "\"" + typeA + "\"is an invalid type (only int or bool).");
                            }

                            AvatarAttribute aa;
                            if (tryToCorrectErrors) {
                                if (at != AvatarType.UNDEFINED) {
                                    aa = new AvatarAttribute(nameA, at, newBlock, _referenceObject);
                                } else {
                                    aa = new AvatarAttribute(nameA, AvatarType.INTEGER, newBlock, _referenceObject);
                                }
                            } else {
                                aa = new AvatarAttribute(nameA, at, newBlock, _referenceObject);
                            }
                            newBlock.addAttribute(aa);
                            am.addParameter(aa);
                        }
                        String returnT = methodsA.getJSONObject(j).getString("returnType");
                        AvatarType at = AvatarType.getType(returnT);

                        if (tryToCorrectErrors) {
                            if (at != AvatarType.UNDEFINED) {
                                am.addReturnParameter(new AvatarAttribute("returnType", at, newBlock, _referenceObject));
                            } else {
                                // We remove the return type
                            }
                        } else {
                            am.addReturnParameter(new AvatarAttribute("returnType", at, newBlock, _referenceObject));
                        }

                        newBlock.addMethod(am);
                    }
                } catch (JSONException je) {
                }

                try {
                    JSONArray signalS = blockO.getJSONArray("signals");
                    for (int j = 0; j < signalS.length(); j++) {
Ludovic Apvrille's avatar
Ludovic Apvrille committed
                        String nameS = signalS.getJSONObject(j).getString("signal");
                        if (nameS.startsWith("input")) {
                            nameS = nameS.substring(5).trim();
                            nameS = "in " + nameS;
                        } else if (nameS.startsWith("output")) {
                            nameS = nameS.substring(6).trim();
                            nameS = "out " + nameS;
                            jsonErrors.add("In block " + newBlock.getName() + " signal " + nameS + " is invalid because " +
                                    "it must start with \"in\" or \"out\".");
                            nameS = nameS.substring(6).trim();
                            nameS = "in " + nameS;
Ludovic Apvrille's avatar
Ludovic Apvrille committed
                        AvatarSignal as = AvatarSignal.isAValidSignalThenCreate(nameS, newBlock);

                        /*JSONArray params = signalS.getJSONObject(j).getJSONArray("parameters");
                        for (int k = 0; k < params.length(); k++) {
                            String nameA = spec.removeSpaces(params.getJSONObject(k).getString("name"));
                            String typeA = params.getJSONObject(k).getString("type");
                            AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject);
                            as.addParameter(aa);
Ludovic Apvrille's avatar
Ludovic Apvrille committed
                        }*/
Ludovic Apvrille's avatar
Ludovic Apvrille committed
                        if (as != null) {
                            TraceManager.addDev("Added signal: " + nameS);
Ludovic Apvrille's avatar
Ludovic Apvrille committed
                            newBlock.addSignal(as);
                        } else {
                            TraceManager.addDev("Invalid signal: " + nameS);
                            jsonErrors.add("In block " + newBlock.getName() + " signal " + nameS + " is invalid.");

        // Connecting signals with identical names
        HashSet<AvatarSignal> signalSet = new HashSet<>();
        HashSet<AvatarSignal> toBeRemoved = new HashSet<>();


        // We put all signals in a HashMap.
        // We try to connect them
        // Unconnected signals are removed from their respective blocks
        HashMap<AvatarSignal, AvatarBlock> mapOfSignals = new HashMap<>();
        for (AvatarBlock block : spec.getListOfBlocks()) {
            for (AvatarSignal sig : block.getSignals()) {
                mapOfSignals.put(sig, block);
            }
        }
        HashMap<AvatarSignal, AvatarBlock> connectedSignalsToBeRemoved = new HashMap<>();
        for (AvatarSignal sig : mapOfSignals.keySet()) {
            if (sig.isOut()) {
                AvatarSignal inSig = spec.getSignalWithNameAndDirection(sig.getName(), AvatarSignal.IN);
                if (inSig != null) {
                    // We can do the connection
                    if (!sig.isCompatibleWith(inSig)) {
                        if (tryToCorrectErrors) {
                            // inSig parameters are used, and the definition of outSig is changed
                            sig.getListOfAttributes().clear();
                            for (AvatarAttribute aa : inSig.getListOfAttributes()) {
                                sig.addParameter(aa.clone());
                            }
                            AvatarBlock blockO = mapOfSignals.get(sig);
                            AvatarBlock blockD = mapOfSignals.get(inSig);
                            AvatarRelation ar = spec.getAvatarRelationWithBlocks(blockO, blockD, true);
                            if (ar == null) {
                                ar = new AvatarRelation("relation", blockO, blockD, _referenceObject);
                                ar.setAsynchronous(false);
                                ar.setPrivate(true);
                                spec.addRelation(ar);
                            }
                            // If the signals have the same name and are in the same block, they are renamed
                            if ((sig.getName().compareTo(inSig.getName()) == 0) && (blockO == blockD)) {
                                sig.setName(sig.getName() + "_out");
                                inSig.setName(sig.getName() + "_in");
                            }
                            ar.addSignals(sig, inSig);
                            TraceManager.addDev("----------> Connecting " + sig.getName() + " to " + inSig.getName());
                            connectedSignalsToBeRemoved.put(sig, blockO);
                            connectedSignalsToBeRemoved.put(inSig, blockD);
                        } else {
                            jsonErrors.add("Signal " + sig.getName() + " of block " + mapOfSignals.get(sig).getName() + " cannot be " +
                                    "connected to signal " + inSig.getName() + " of block " + mapOfSignals.get(inSig).getName() +
                                    " because their list of attributes is not compatible.");
                } else {
                    jsonErrors.add("In block " + mapOfSignals.get(sig).getName() + " signal " + sig.getName() + " cannot be connected because" +
                            " there exists no other in signal with the same name.");
        for (AvatarSignal sig : connectedSignalsToBeRemoved.keySet()) {
            mapOfSignals.remove(sig);
        }
Ludovic Apvrille's avatar
Ludovic Apvrille committed

        for (AvatarSignal sig : mapOfSignals.keySet()) {
            jsonErrors.add("In block " + mapOfSignals.get(sig).getName() + " signal must be connected to another signal");
            if (tryToCorrectErrors) {
                mapOfSignals.get(sig).removeAvatarSignal(sig);
            }
        }
Ludovic Apvrille's avatar
Ludovic Apvrille committed


Ludovic Apvrille's avatar
Ludovic Apvrille committed

Ludovic Apvrille's avatar
Ludovic Apvrille committed

    // We remove all non-connected blocks if at least two blocks have a relation
    public void removeNonConnectedBlocks() {
Ludovic Apvrille's avatar
Ludovic Apvrille committed
        TraceManager.addDev("Removing non connected blocks");
        boolean found = false;
        for (AvatarRelation ar : relations) {
            if (ar.getBlock1() != ar.getBlock2()) {
                found = true;
                break;
            }
        }
        if (found) {
            ArrayList<AvatarBlock> toBeRemovedNotConnected = new ArrayList<>();
            for (AvatarBlock ab : getListOfBlocks()) {
                boolean foundBlock = false;
                for (AvatarRelation ar : relations) {
                    if (ar.getBlock1() == ab || ar.getBlock2() == ab) {
                        foundBlock = true;
                        break;
                    }
                }
                if (!foundBlock) {
                    toBeRemovedNotConnected.add(ab);
                }
            }
Ludovic Apvrille's avatar
Ludovic Apvrille committed

            if (toBeRemovedNotConnected.size() > 0) {
                TraceManager.addDev("Found blocks to be removed: " + toBeRemovedNotConnected.size() + " blocks");
                getListOfBlocks().removeAll(toBeRemovedNotConnected);
            }

    public static AvatarSpecification fromJSONConnection(String _spec, String _name, Object _referenceObject, boolean tryToCorrectErrors) {
        if (_spec == null) {
            return null;
        }
Ludovic Apvrille's avatar
Ludovic Apvrille committed


        AvatarSpecification spec = new AvatarSpecification(_name, _referenceObject);
        jsonErrors = new ArrayList<>();
Ludovic Apvrille's avatar
Ludovic Apvrille committed

        int indexStart = _spec.indexOf('{');
        int indexStop = _spec.lastIndexOf('}');
Ludovic Apvrille's avatar
Ludovic Apvrille committed

        if ((indexStart == -1) || (indexStop == -1) || (indexStart > indexStop)) {
            throw new org.json.JSONException("Invalid JSON object (start)");
        }
Ludovic Apvrille's avatar
Ludovic Apvrille committed

        _spec = _spec.substring(indexStart, indexStop + 1);
        //TraceManager.addDev("Cut spec: " + _spec);
        JSONObject mainObject = new JSONObject(_spec);
        JSONArray connections = mainObject.getJSONArray("connections");

        if (connections == null) {
            TraceManager.addDev("No connections in json");
            return spec;
        }

        for (int i = 0; i < connections.length(); i++) {
            JSONObject conn = connections.getJSONObject(i);
            String sigName = spec.removeSpaces(conn.getString("signal"));
            String blockOName = spec.removeSpaces(conn.getString("nameOriginBlock"));
            String blockDName = spec.removeSpaces(conn.getString("nameDestinationBlock"));
            if (sigName == null) {
                jsonErrors.add("connection #" + i + " does not have a \"signal\" element");
            if (blockOName == null) {
                jsonErrors.add("connection #" + i + " does not have a \"nameOriginBlock\" element");
            }
            if (blockDName == null) {
                jsonErrors.add("connection #" + i + " does not have a \"nameDestinationBlock\" element");
            }
            if ((sigName != null) && (blockOName != null) && (blockDName != null)) {
                TraceManager.addDev("Handling signal " + sigName + " from " + blockOName + " to " + blockDName);

                AvatarBlock blockO = spec.getBlockWithName(blockOName);
                if (blockO == null) {
                    blockO = new AvatarBlock(blockOName, spec, _referenceObject);
                    spec.addBlock(blockO);
                }
                AvatarBlock blockD = spec.getBlockWithName(blockDName);
                if (blockD == null) {
                    blockD = new AvatarBlock(blockDName, spec, _referenceObject);
                    spec.addBlock(blockD);
                }
                AvatarSignal asO = AvatarSignal.isAValidSignalThenCreate("out " + sigName, blockO);
                if (asO == null) {
                    jsonErrors.add("The declaration of the out signal " + sigName + " is not valid for block " + blockOName);
                    AvatarSignal asD;
                    if (blockO == blockD) {
                        asD = AvatarSignal.isAValidSignalThenCreate("in " + sigName + "_IN", blockD);
                        TraceManager.addDev("Added in signal on ITSELF: " + asD.getName());
                    } else {
                        asD = AvatarSignal.isAValidSignalThenCreate("in " + sigName, blockD);
                    }
                    if (asD == null) {
                        jsonErrors.add("The declaration of the in signal " + sigName + " is not valid for block " + blockDName);
                    } else {
                        if ((asO != null) && (asD != null)) {
                            AvatarRelation ar = spec.getAvatarRelationWithBlocks(blockO, blockD, true);
                            if (ar == null) {
                                ar = new AvatarRelation("relation", blockO, blockD, _referenceObject);
                                ar.setAsynchronous(false);
                                ar.setPrivate(true);
                                spec.addRelation(ar);
                            }

                            blockO.addSignal(asO);
                            blockD.addSignal(asD);
                            ar.addSignals(asO, asD);
                            TraceManager.addDev("Connecting " + asO.getName() + " to " + asD.getName());
                        }
        spec.removeNonConnectedBlocks();

    }

    public void addSignalsAndConnection(AvatarSpecification _as) {
        ArrayList<AvatarBlock> blocksToBeAdded = new ArrayList<>();
        for (AvatarBlock _block : _as.getListOfBlocks()) {
            AvatarBlock block = getBlockWithName(_block.getName());
            if (block == null) {
                blocksToBeAdded.add(_block);
        }
        _as.getListOfBlocks().addAll(blocksToBeAdded);
        ArrayList<AvatarSignal> signalsToBeAdded = new ArrayList<>();
        for (AvatarBlock _block : _as.getListOfBlocks()) {
            for (AvatarSignal _sig : _block.getSignals()) {
                AvatarBlock block = getBlockWithName(_block.getName());
                if (block != null) {
                    AvatarSignal sig = block.getAvatarSignalWithName(_as.getName());
                    if (sig == null) {
                        block.addSignal(_sig);
                    }
        for (AvatarRelation _ar : _as.getRelations()) {
            AvatarBlock blockO = getBlockWithName(_ar.getBlock1().getName());
            AvatarBlock blockD = getBlockWithName(_ar.getBlock2().getName());
            if ((blockO != null) && (blockD != null)) {
                AvatarRelation ar = new AvatarRelation("relation", blockO, blockD, _ar.getReferenceObject());
                ar.setAsynchronous(_ar.isAsynchronous());
                ar.setPrivate(_ar.isPrivate());
                addRelation(ar);
                for (int i = 0; i < _ar.getSignals1().size(); i++) {
                    AvatarSignal _sig1 = _ar.getSignal1(i);
                    AvatarSignal _sig2 = _ar.getSignal2(i);

                    AvatarSignal sig1 = blockO.getAvatarSignalWithName(_sig1.getName());
                    AvatarSignal sig2 = blockD.getAvatarSignalWithName(_sig2.getName());

                    if ((sig1 != null) && (sig2 != null)) {
                        if (sig1.isCompatibleWith(sig2)) {
                            ar.addSignals(sig1, sig2);
                        }
                    }
    public void makeMinimalStateMachines() {
        for (AvatarBlock block : blocks) {
            block.makeMinimalStateMachine();
        }
    }
    public void improveNames() {
        for (AvatarBlock block : blocks) {
            block.setName(Conversion.capitalizeFirstLetter(block.getName()));
            for (AvatarAttribute aa : block.getAttributes()) {
                aa.setName(Conversion.lowercaseFirstLetter(aa.getName()));
            }
            for (AvatarMethod am : block.getMethods()) {
                am.setName(Conversion.lowercaseFirstLetter(am.getName()));
            }
            for (AvatarSignal as : block.getSignals()) {
                as.setName(Conversion.lowercaseFirstLetter(as.getName()));
            }
        }
    public static ArrayList<String> getJSONErrors() {
        return jsonErrors;
    }
    public static String removeSpaces(String _input) {
        return _input.trim().replaceAll("  ", " ");

    public List<AvatarLibraryFunction> getListOfLibraryFunctions() {
    public void addLibraryFunction(AvatarLibraryFunction libraryFunction) {
        this.libraryFunctions.add(libraryFunction);
    }

    // For code generation
    public void addApplicationCode(String _code) {
        if (_code == null) {
            return;
        }
        if (applicationCode == null) {
            applicationCode = _code;
            return;
        }
        applicationCode += _code + "\n";
    }

    public String getApplicationCode() {
        if (applicationCode == null) {
            return "";
        }
        return applicationCode;
    }

    public boolean hasApplicationCode() {
        if (applicationCode == null) {
            return false;
        }
        return (applicationCode.indexOf("__user_init()") != -1);
    }

    public Object getInformationSource() {
        return informationSource;
    }

    public void setInformationSource(Object o) {
        informationSource = o;
    }

    public List<AvatarBlock> getListOfBlocks() {
        return blocks;
    }

    public List<AvatarAMSInterface> getListOfInterfaces() {
    public List<AvatarRelation> getRelations() {
        return relations;
    }

    public List<AvatarDataType> getDataTypes() {
        return dataTypes;
    }

    public List<AvatarPragma> getPragmas() {
        return pragmas;
    }
    public List<String> getSafetyPragmas() {
        return safetyPragmas;
    public List<AvatarPragmaLatency> getLatencyPragmas() {
        return latencyPragmas;
    public List<AvatarConstant> getAvatarConstants() {
        return constants;
    }

    public HashMap<String, String> getSafetyPragmasRefs() {
        return safetyPragmasRefs;
    }

    public int getNbOfASMGraphicalElements() {
        int cpt = 0;
        for (AvatarBlock block : blocks) {
            cpt += block.getNbOfASMGraphicalElements();
        }
        return cpt;
    }

    public boolean isASynchronousSignal(AvatarSignal _as) {
        for (AvatarRelation ar : relations) {
            if (ar.containsSignal(_as)) {
                return !(ar.isAsynchronous());
            }
        }

        return false;
    }

    public AvatarSignal getCorrespondingSignal(AvatarSignal _as) {
        for (AvatarRelation ar : relations) {
            if (ar.containsSignal(_as)) {
                int index = ar.hasSignal(_as);
                return ar.getInSignal(index);
            }
        }
        return null;
    }

    public boolean ASynchronousExist() {
        List<AvatarRelation> asynchro = getRelations();

        for (AvatarRelation ar : asynchro)
            if (ar.isAsynchronous())
                return true;

        return false;
    }

    public boolean AMSExist() {
        List<AvatarRelation> ams = getRelations();

        for (AvatarRelation ar : ams)
            if (ar.isAMS())
                return true;

        return false;
    }

    // end DG
    public void addBlock(AvatarBlock _block) {
        blocks.add(_block);
    }

    /*public void addBroadcastSignal(AvatarSignal _as) {
      if (!broadcast.containsSignal(_as)) {
      broadcast.addSignal(_as);
      }
      }

      public AvatarBroadcast getBroadcast() {
      return broadcast;
      }*/

    public void addInterface(AvatarAMSInterface _interface) {
        interfaces.add(_interface);
    }

    public void addRelation(AvatarRelation _relation) {
        relations.add(_relation);
    }

    public void addDataType(AvatarDataType _adt) {
        dataTypes.add(_adt);
    }

    public void addInterfaceRelation(AvatarInterfaceRelation _irelation) {
        irelations.add(_irelation);
    }

    public void addPragma(AvatarPragma _pragma) {
        pragmas.add(_pragma);
    }
    public void addSafetyPragma(String _pragma, String _refPragmas) {
        safetyPragmas.add(_pragma);
        safetyPragmasRefs.put(_pragma, _refPragmas);
    public void addLatencyPragma(AvatarPragmaLatency _pragma) {
        latencyPragmas.add(_pragma);
    public void addConstant(AvatarConstant _constant) {
        //Only add unique constants
        if (this.getAvatarConstantWithName(_constant.getName()) == null) {
            constants.add(_constant);
        }
    public AvatarDataType getDataTypeByName(String _name) {
        for(AvatarDataType adt: dataTypes) {
            if (adt.getName().compareTo(_name) == 0) {
                return adt;
            }
        }
        return null;
    }

    public List<String> keepOnlyOriginalValues(List<String> input) {
        List<String> ret = new LinkedList<>();
        String currentStart = "";
        for(String s: input) {
            int index = s.indexOf("__");
            if (index > 0) {
                String start = s.substring(0, index);
                if (start.compareTo(currentStart) != 0) {
                    ret.add(start);
                    currentStart = start;
                }
            } else {
                ret.add(s);
                currentStart = "";
            }
        }
        return ret;
    }

Dominique Blouin's avatar
Dominique Blouin committed
    @Override
        return toStringRecursive(false);
        //Thread.currentThread().dumpStack();
    }

    public String toStringRecursive(boolean isRecursive) {
        //Thread.currentThread().dumpStack();
        StringBuffer sb = new StringBuffer("Blocks:\n");
        for (AvatarBlock block : blocks) {
            if (!isRecursive) {
                sb.append("*** " + block.toString() + "\n");
            } else {
                sb.append("*** " + block.toStringRecursive() + "\n");
            }
        for (AvatarRelation relation : relations) {
            sb.append("Relation:" + relation.toString() + "\n");
        }
        sb.append("\nData types:\n");
        for (AvatarDataType type : dataTypes) {
            sb.append("Data type:" + type.toString() + "\n");
        }
        for (AvatarPragma pragma : pragmas) {
            sb.append("Pragma:" + pragma.toString() + "\n");
        }
        for (AvatarConstant constant : constants) {
            sb.append("Constant:" + constant.toString() + "\n");
        }
        return sb.toString();
    public String toTextFormat(boolean putSMD, boolean putPragmas, boolean putConstants) {
        //Thread.currentThread().dumpStack();
        StringBuffer sb = new StringBuffer("Blocks:\n");
        //TraceManager.addDev("TS Block");
        for (AvatarBlock block : blocks) {
            sb.append("*** " + block.toTextFormat(putSMD) + "\n");

        }
        //TraceManager.addDev("TS Relations");
        sb.append("\nRelations:\n");
        for (AvatarRelation relation : relations) {
            sb.append("\tRelation:" + relation.toString() + "\n");
        }
        if (putPragmas) {
            sb.append("\nPragmas:\n");
            for (AvatarPragma pragma : pragmas) {
                sb.append("\tPragma:" + pragma.toString() + "\n");
            }

        if (putConstants) {
            for (AvatarConstant constant : constants) {
                sb.append("\tConstant:" + constant.toString() + "\n");
            }
        }

        //TraceManager.addDev("TS All done");

        return sb.toString();
    }

    public String toShortString() {
        //TraceManager.addDev("To Short String");
        //Thread.currentThread().dumpStack();
        StringBuffer sb = new StringBuffer("Blocks:\n");
        for (AvatarBlock block : blocks) {
            sb.append("*** " + block.toShortString() + "\n");
        }
        sb.append("\nRelations:\n");
        for (AvatarRelation relation : relations) {
            sb.append("Relation:" + relation.toString() + "\n");
        }
        /*for (AvatarConstant constant: constants){
            sb.append("Constant:" + constant.toString() + "\n");
        }*/

        return sb.toString();
    }

    public AvatarBlock getBlockWithName(String _name) {
        for (AvatarBlock block : blocks) {
            if (block.getName().compareTo(_name) == 0) {
tempiaa's avatar
tempiaa committed
    public int getBlockIndex(AvatarBlock _block) {
        int cpt = 0;
        for (AvatarBlock block : blocks) {
tempiaa's avatar
tempiaa committed
            if (block == _block) {
                return cpt;
            }
            cpt++;
        }
tempiaa's avatar
tempiaa committed
        return -1;
    }
Ludovic Apvrille's avatar
Ludovic Apvrille committed
    public AvatarBlock getBlockWithSignal(String signalName) {
        for (AvatarBlock b : blocks) {
Ludovic Apvrille's avatar
Ludovic Apvrille committed
            if (b.getSignalByName(signalName) != null) {
                return b;
            }
        }
        return null;
    }

    public AvatarBlock getBlockWithSignal(AvatarSignal as) {
        for (AvatarBlock b : blocks) {
            if (b.getSignals().contains(as)) {
                return b;
            }
        }
        return null;
    }

    public AvatarSignal getSignalWithNameAndDirection(String name, int direction) {
        for (AvatarBlock block : blocks) {
            for (AvatarSignal as : block.getSignals()) {
                if ((as.getSignalName().compareTo(name) == 0) && (as.getInOut() == direction)) {
                    return as;
                }
            }
        }
        return null;
    }

    public AvatarAMSInterface getAMSInterfaceWithName(String _name) {
        for (AvatarAMSInterface interf : interfaces) {
            if (interf.getName().compareTo(_name) == 0) {
    public AvatarConstant getAvatarConstantWithName(String _name) {
        for (AvatarConstant constant : constants) {
            if (constant.getName().compareTo(_name) == 0) {
Dominique Blouin's avatar
Dominique Blouin committed

    /* Generates the Expression Solvers, returns the AvatarStateMachineElement
     * containing the errors */
    public List<AvatarStateMachineElement> generateAllExpressionSolvers() {
        List<AvatarStateMachineElement> errors = new ArrayList<>();
        AvatarTransition at;
        boolean returnVal;
Sophie Coudert's avatar
Sophie Coudert committed
        //AvatarExpressionSolver.emptyAttributesMap();
        for (AvatarBlock block : getListOfBlocks()) {
            AvatarStateMachine asm = block.getStateMachine();

            for (AvatarStateMachineElement elt : asm.getListOfElements()) {
                if (elt instanceof AvatarTransition) {