
org.intocps.maestro.plugin.DataExchangeHandler Maven / Gradle / Ivy
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