All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.intocps.maestro.plugin.DataExchangeHandler Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
package org.intocps.maestro.plugin;

import org.intocps.maestro.ast.LexIdentifier;
import org.intocps.maestro.ast.node.*;
import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment;
import org.intocps.maestro.framework.fmi2.RelationVariable;
import org.intocps.maestro.fmi.ModelDescription;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.intocps.maestro.ast.MableAstFactory.*;

public class DataExchangeHandler {

    private final Set outputRelations;
    private final Map>> outputs;
    private final Set inputRelations;
    private final Map>> inputs;
    Function getCompStatusDesignator;
    BiConsumer, Map.Entry>> checkStatus;

    public DataExchangeHandler(Set relations, Fmi2SimulationEnvironment env,
            Function getCompStatusDesignator,
            BiConsumer, Map.Entry>> checkStatus) {
        this.checkStatus = checkStatus;
        this.getCompStatusDesignator = getCompStatusDesignator;
        outputRelations = relations.stream().filter(r -> r.getDirection() == Fmi2SimulationEnvironment.Relation.Direction.OutputToInput)
                .collect(Collectors.toSet());

        // outputs contains both outputs based on relations and outputs based on additional variables to log
        outputs = outputRelations.stream().map(r -> r.getSource().scalarVariable.instance).distinct().collect(Collectors
                .toMap(Function.identity(), s -> outputRelations.stream().filter(r -> r.getSource().scalarVariable.instance.equals(s)).flatMap(r -> {
                    List outputs_ =
                            env.getVariablesToLog(s.getText()).stream().map(x -> x.scalarVariable).collect(Collectors.toList());
                    //outputs_.add(r.getSource().scalarVariable.getScalarVariable());
                    return outputs_.stream();
                }).distinct().collect(Collectors.groupingBy(sv -> sv.getType().type))));

        // We need to add the additional

        inputRelations = relations.stream().filter(r -> r.getDirection() == Fmi2SimulationEnvironment.Relation.Direction.InputToOutput)
                .collect(Collectors.toSet());

        inputs = inputRelations.stream().map(r -> r.getSource().scalarVariable.instance).distinct().collect(Collectors.toMap(Function.identity(),
                s -> inputRelations.stream().filter(r -> r.getSource().scalarVariable.instance.equals(s))
                        .map(r -> r.getSource().scalarVariable.getScalarVariable()).collect(Collectors.groupingBy(sv -> sv.getType().type))));

    }

    static String getFmiGetName(ModelDescription.Types type, UsageType usage) {

        String fun = usage == UsageType.In ? "set" : "get";
        switch (type) {
            case Boolean:
                return fun + "Boolean";
            case Real:
                return fun + "Real";
            case Integer:
                return fun + "Integer";
            case String:
                return fun + "String";
            case Enumeration:
            default:
                return null;
        }
    }

    static SPrimitiveType convert(ModelDescription.Types type) {
        switch (type) {

            case Boolean:
                return newABoleanPrimitiveType();
            case Real:
                return newARealNumericPrimitiveType();
            case Integer:
                return newAIntNumericPrimitiveType();
            case String:
                return newAStringPrimitiveType();
            case Enumeration:
            default:
                return null;
        }
    }

    static LexIdentifier getBufferName(LexIdentifier comp, ModelDescription.Types type, UsageType usage) {
        return getBufferName(comp, convert(type), usage);
    }

    static LexIdentifier getBufferName(LexIdentifier comp, SPrimitiveType type, UsageType usage) {

        String t = getTypeId(type);

        return newAIdentifier(comp.getText() + t + usage);
    }

    static String getTypeId(SPrimitiveType type) {
        String t = type.getClass().getSimpleName();

        if (type instanceof ARealNumericPrimitiveType) {
            t = "R";
        } else if (type instanceof AIntNumericPrimitiveType) {
            t = "I";
        } else if (type instanceof AStringPrimitiveType) {
            t = "S";
        } else if (type instanceof ABooleanPrimitiveType) {
            t = "B";
        }
        return t;
    }

    public Map>> getOutputs() {
        return outputs;
    }

    public Set getInputRelations() {
        return inputRelations;
    }

    LexIdentifier getVrefName(LexIdentifier comp, ModelDescription.Types type, UsageType usage) {

        return newAIdentifier(comp.getText() + "Vref" + getTypeId(convert(type)) + usage);
    }

    public List allocate() {
        List statements = new Vector<>();

        //create output buffers
        outputs.forEach((comp, map) -> map.forEach((type, vars) -> statements.add(newALocalVariableStm(
                newAVariableDeclaration(getBufferName(comp, type, UsageType.Out), newAArrayType(convert(type)), vars.size(), null)))));

        outputs.forEach((comp, map) -> map.forEach((type, vars) -> statements.add(newALocalVariableStm(
                newAVariableDeclaration(getVrefName(comp, type, UsageType.Out), newAArrayType(newAUIntNumericPrimitiveType()), vars.size(),
                        newAArrayInitializer(vars.stream().map(v -> newAIntLiteralExp((int) v.valueReference)).collect(Collectors.toList())))))));

        //create input buffers
        inputs.forEach((comp, map) -> map.forEach((type, vars) -> statements.add(newALocalVariableStm(
                newAVariableDeclaration(getBufferName(comp, type, UsageType.In), newAArrayType(convert(type)), vars.size(), null)))));

        inputs.forEach((comp, map) -> map.forEach((type, vars) -> statements.add(newALocalVariableStm(
                newAVariableDeclaration(getVrefName(comp, type, UsageType.In), newAArrayType(newAUIntNumericPrimitiveType()), vars.size(),
                        newAArrayInitializer(vars.stream().map(v -> newAIntLiteralExp((int) v.valueReference)).collect(Collectors.toList())))))));


        return statements;
    }

    public List getAll(boolean inSimulationLoop) {

        //get outputs
        BiConsumer> getAll = (inLoop, list) -> outputs.forEach((comp, map) -> map.forEach((type, vars) -> {
            list.add(newAAssignmentStm(getCompStatusDesignator.apply(comp),
                    newACallExp(newAIdentifierExp((LexIdentifier) comp.clone()), newAIdentifier(getFmiGetName(type, UsageType.Out)),
                            Arrays.asList(newAIdentifierExp(getVrefName(comp, type, UsageType.Out)), newAIntLiteralExp(vars.size()),
                                    newAIdentifierExp(getBufferName(comp, type, UsageType.Out))))));
            checkStatus.accept(Map.entry(inSimulationLoop, "get failed"), Map.entry(comp, list));
        }));

        List statements = new Vector<>();
        getAll.accept(inSimulationLoop, statements);
        return statements;


    }

    public List setAll() {
        Consumer> setAll = (list) ->
                //set inputs
                inputs.forEach((comp, map) -> map.forEach((type, vars) -> {
                    list.add(newAAssignmentStm(getCompStatusDesignator.apply(comp),
                            newACallExp(newAIdentifierExp((LexIdentifier) comp.clone()), newAIdentifier(getFmiGetName(type, UsageType.In)),
                                    Arrays.asList(newAIdentifierExp(getVrefName(comp, type, UsageType.In)), newAIntLiteralExp(vars.size()),
                                            newAIdentifierExp(getBufferName(comp, type, UsageType.In))))));
                    checkStatus.accept(Map.entry(true, "set failed"), Map.entry(comp, list));
                }));


        List statements = new Vector<>();
        setAll.accept(statements);
        return statements;

    }

    public List exchangeData() {

        Consumer> exchangeData = (list) -> inputRelations.forEach(r -> {
            int toIndex =
                    inputs.get(r.getSource().scalarVariable.instance).get(r.getSource().scalarVariable.getScalarVariable().getType().type).stream()
                            .map(ModelDescription.ScalarVariable::getName).collect(Collectors.toList())
                            .indexOf(r.getSource().scalarVariable.scalarVariable.getName());

            AArrayStateDesignator to = newAArayStateDesignator(newAIdentifierStateDesignator(
                    getBufferName(r.getSource().scalarVariable.instance, r.getSource().scalarVariable.getScalarVariable().getType().type,
                            UsageType.In)), newAIntLiteralExp(toIndex));

            //the relation should be a one to one relation so just take the first one
            RelationVariable fromVar = r.getTargets().values().iterator().next().scalarVariable;
            PExp from = newAArrayIndexExp(newAIdentifierExp(getBufferName(fromVar.instance, fromVar.getScalarVariable().type.type, UsageType.Out)),
                    Collections.singletonList(newAIntLiteralExp(outputs.get(fromVar.instance).get(fromVar.getScalarVariable().getType().type).stream()
                            .map(ModelDescription.ScalarVariable::getName).collect(Collectors.toList()).indexOf(fromVar.scalarVariable.getName()))));

            if (r.getSource().scalarVariable.getScalarVariable().getType().type != fromVar.getScalarVariable().getType().type) {
                //ok the types are not matching, lets use a converter

                AArrayIndexExp toAsExp = newAArrayIndexExp(newAIdentifierExp(
                        getBufferName(r.getSource().scalarVariable.instance, r.getSource().scalarVariable.getScalarVariable().getType().type,
                                UsageType.In)), Arrays.asList(newAIntLiteralExp(toIndex)));

                list.add(newExpressionStm(newACallExp(newExpandToken(), newAIdentifierExp("TypeConverter"), newAIdentifier(
                        "convert" + fromVar.getScalarVariable().getType().type + "2" +
                                r.getSource().scalarVariable.getScalarVariable().getType().type), Arrays.asList(from, toAsExp))));


            } else {
                list.add(newAAssignmentStm(to, from));
            }

        });
        List statements = new Vector<>();
        exchangeData.accept(statements);
        return statements;
    }

    static enum UsageType {
        In,
        Out
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy