Added DistributedTargetGenerator.java + test

parent 2babad19
......@@ -87,6 +87,11 @@
<version>0.0.1c-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>embedded-montiarc-math-rosmsg-generator</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware.yamlbeans</groupId>
......
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ConnectorSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.PortSymbol;
import de.monticore.lang.embeddedmontiarc.tagging.MiddlewareSymbol;
import de.monticore.lang.embeddedmontiarc.tagging.RosConnectionSymbol;
import de.monticore.lang.monticar.generator.roscpp.helper.TagHelper;
import de.monticore.lang.monticar.generator.rosmsg.RosMsg;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.logging.Log;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class DistributedTargetGenerator extends CMakeMasterGenerator {
private RosMsgImpl rosMsgImpl;
public DistributedTargetGenerator(String generationTargetPath) {
setGenerationTargetPath(generationTargetPath);
rosMsgImpl = new RosMsgImpl("rosmsg");
//this.add(rosMsgImpl,"rosmsg/");
}
@Override
public List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver) throws IOException {
Map<PortSymbol, RosConnectionSymbol> resolvedTags = TagHelper.resolveTags(taggingResolver, componentInstanceSymbol);
Map<ExpandedComponentInstanceSymbol, GeneratorImpl> generatorMap = new HashMap<>();
fixComponentInstance(componentInstanceSymbol);
Collection<ExpandedComponentInstanceSymbol> subComps = getSubComponentInstances(componentInstanceSymbol);
//TODO: cluster non mw subcomps together with mw subcomps
boolean allSubsMwOnly = subComps.stream()
.flatMap(comp -> comp.getPorts().stream())
.allMatch(p -> p.getMiddlewareSymbol().isPresent());
if (allSubsMwOnly) {
subComps.forEach(comp ->
generatorMap.put(comp, createFullGenerator(comp.getFullName().replace(".", "_")))
);
} else {
generatorMap.put(componentInstanceSymbol, createFullGenerator(componentInstanceSymbol.getFullName().replace(".", "_")));
}
List<File> files = new ArrayList<>();
CMakeMasterGenerator cmakeListsGenerator = new CMakeMasterGenerator();
cmakeListsGenerator.setGenerationTargetPath(generationTargetPath);
for (ExpandedComponentInstanceSymbol comp : generatorMap.keySet()) {
files.addAll(generatorMap.get(comp).generate(comp, taggingResolver));
//add empty generator to cmakeListsGenerator so that CMakeLists.txt will be generated
cmakeListsGenerator.add(new GeneratorImpl() {
}, comp.getFullName().replace(".", "_"));
}
files.addAll(cmakeListsGenerator.generate(componentInstanceSymbol, taggingResolver));
return files;
}
private GeneratorImpl createFullGenerator(String subdir) {
MiddlewareMasterGenerator res = new MiddlewareMasterGenerator();
res.setGenerationTargetPath(generationTargetPath + (subdir.endsWith("/") ? subdir : subdir + "/"));
this.getGeneratorImpls().forEach(gen -> res.add(gen, this.getImplSubfolder(gen)));
return res;
}
private void fixComponentInstance(ExpandedComponentInstanceSymbol componentInstanceSymbol) {
fixRosTopics(componentInstanceSymbol);
}
private void fixRosTopics(ExpandedComponentInstanceSymbol componentInstanceSymbol) {
componentInstanceSymbol.getConnectors().stream()
.filter(connectorSymbol -> connectorSymbol.getSourcePort().isRosPort() && connectorSymbol.getTargetPort().isRosPort())
.forEach(connectorSymbol -> {
if (Objects.equals(connectorSymbol.getSourcePort().getComponentInstance().orElse(null), componentInstanceSymbol)) {
//In port of supercomp
inferRosConnectionIfPossible(connectorSymbol.getSourcePort(), connectorSymbol.getTargetPort());
} else if (Objects.equals(connectorSymbol.getTargetPort().getComponentInstance().orElse(null), componentInstanceSymbol)) {
//out port of supercomp
inferRosConnectionIfPossible(connectorSymbol.getTargetPort(), connectorSymbol.getSourcePort());
} else {
//In between subcomps
generateRosConnectionIfPossible(connectorSymbol);
}
});
}
private void generateRosConnectionIfPossible(ConnectorSymbol connectorSymbol) {
MiddlewareSymbol sourceTag = connectorSymbol.getSourcePort().getMiddlewareSymbol().orElse(null);
MiddlewareSymbol targetTag = connectorSymbol.getTargetPort().getMiddlewareSymbol().orElse(null);
if (sourceTag == null || targetTag == null || !sourceTag.isKindOf(RosConnectionSymbol.KIND) || !targetTag.isKindOf(RosConnectionSymbol.KIND)) {
Log.debug("Both sourcePort and targetPort need to have a RosConnectionSymbol", "RosConnectionSymbol");
return;
}
RosConnectionSymbol rosConnectionA = (RosConnectionSymbol) sourceTag;
RosConnectionSymbol rosConnectionB = (RosConnectionSymbol) targetTag;
RosConnectionSymbol emptyRosConnection = new RosConnectionSymbol();
if (!rosConnectionA.equals(emptyRosConnection) || !rosConnectionB.equals(emptyRosConnection)) {
Log.debug("Will not override rosConnections that are not empty!", "RosConnectionSymbol");
return;
}
//target port name is unique: each in port can only have one connection!
String topicName = connectorSymbol.getTargetPort().getFullName().replace(".", "_");
RosMsg rosTypeA = rosMsgImpl.getRosType(connectorSymbol.getTargetPort().getTypeReference());
RosMsg rosTypeB = rosMsgImpl.getRosType(connectorSymbol.getSourcePort().getTypeReference());
if (!rosTypeA.equals(rosTypeB)) {
Log.error("topicType mismatch! "
+ connectorSymbol.getSourcePort().getFullName() + " has " + rosTypeB + " and "
+ connectorSymbol.getTargetPort().getFullName() + " has " + rosTypeA);
return;
}
rosMsgImpl.addRosTypeToGenerate(connectorSymbol.getTargetPort().getTypeReference());
if (rosTypeA.getFields().size() == 1) {
connectorSymbol.getSourcePort().setMiddlewareSymbol(new RosConnectionSymbol(topicName, rosTypeB.getName(), rosTypeB.getFields().get(0).getName()));
connectorSymbol.getTargetPort().setMiddlewareSymbol(new RosConnectionSymbol(topicName, rosTypeA.getName(), rosTypeA.getFields().get(0).getName()));
} else {
connectorSymbol.getSourcePort().setMiddlewareSymbol(new RosConnectionSymbol(topicName, rosTypeB.getName()));
connectorSymbol.getTargetPort().setMiddlewareSymbol(new RosConnectionSymbol(topicName, rosTypeA.getName()));
}
}
private void inferRosConnectionIfPossible(PortSymbol sourcePort, PortSymbol targetPort) {
MiddlewareSymbol sourceTag = sourcePort.getMiddlewareSymbol().orElse(null);
MiddlewareSymbol targetTag = targetPort.getMiddlewareSymbol().orElse(null);
if (sourceTag == null || targetTag == null || !sourceTag.isKindOf(RosConnectionSymbol.KIND) || !targetTag.isKindOf(RosConnectionSymbol.KIND)) {
Log.debug("Both sourcePort and targetPort need to have a RosConnectionSymbol", "RosConnectionSymbol");
return;
}
RosConnectionSymbol sourceRosConnection = (RosConnectionSymbol) sourceTag;
RosConnectionSymbol targetRosConnection = (RosConnectionSymbol) targetTag;
if (sourceRosConnection.getTopicName().isPresent() && !targetRosConnection.getTopicName().isPresent())
targetRosConnection.setTopicName(sourceRosConnection.getTopicName().get());
if (sourceRosConnection.getTopicType().isPresent() && !targetRosConnection.getTopicType().isPresent())
targetRosConnection.setTopicType(sourceRosConnection.getTopicType().get());
if (sourceRosConnection.getMsgField().isPresent() && !targetRosConnection.getMsgField().isPresent())
targetRosConnection.setMsgField(sourceRosConnection.getMsgField().get());
}
private Collection<ExpandedComponentInstanceSymbol> getSubComponentInstances(ExpandedComponentInstanceSymbol componentInstanceSymbol) {
//TODO: check which subcomponents are mw only
//TODO: (build clusters?)
return componentInstanceSymbol.getSubComponents();
}
}
......@@ -2,7 +2,6 @@ package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.roscpp.GeneratorRosCpp;
import de.monticore.lang.monticar.generator.roscpp.helper.TagHelper;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import java.io.File;
......@@ -17,7 +16,7 @@ public class RosCppImpl implements GeneratorImpl {
GeneratorRosCpp generatorRosCpp = new GeneratorRosCpp();
generatorRosCpp.setGenerateCMake(true);
generatorRosCpp.setGenerationTargetPath(generationTargetPath);
return TagHelper.generate(generatorRosCpp, taggingResolver, componentInstanceSymbol);
return generatorRosCpp.generateFiles(componentInstanceSymbol, taggingResolver);
}
@Override
......
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.rosmsg.GeneratorRosMsg;
import de.monticore.lang.monticar.generator.rosmsg.RosMsg;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.monticore.lang.monticar.ts.references.MCTypeReference;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class RosMsgImpl implements GeneratorImpl {
private GeneratorRosMsg generatorRosMsg;
private List<MCTypeReference<? extends MCTypeSymbol>> rosTypesToGenerate = new ArrayList<>();
private String packageName;
public RosMsgImpl(String packageName) {
this.packageName = packageName;
generatorRosMsg = new GeneratorRosMsg();
}
@Override
public List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver) throws IOException {
List<File> files = new ArrayList<>();
for (MCTypeReference<? extends MCTypeSymbol> type : rosTypesToGenerate) {
files.addAll(generatorRosMsg.generate(type));
}
return files;
}
@Override
public void setGenerationTargetPath(String path) {
generatorRosMsg.setTarget(path, packageName);
}
public void addRosTypeToGenerate(MCTypeReference<? extends MCTypeSymbol> typeReference) {
rosTypesToGenerate.add(typeReference);
}
public RosMsg getRosType(MCTypeReference<? extends MCTypeSymbol> typeReference) {
return generatorRosMsg.getRosType(typeReference);
}
}
......@@ -2,7 +2,9 @@ package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.tagging.RosToEmamTagSchema;
import de.monticore.lang.monticar.generator.roscpp.helper.TagHelper;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
......@@ -11,6 +13,11 @@ import static org.junit.Assert.assertNotNull;
public class GenerationTest extends AbstractSymtabTest {
@Before
public void initTest() {
TagHelper.reset();
}
@Test
public void testBasicGeneration() throws IOException {
TaggingResolver taggingResolver = createSymTabAndTaggingResolver("src/test/resources/");
......@@ -18,6 +25,7 @@ public class GenerationTest extends AbstractSymtabTest {
ExpandedComponentInstanceSymbol componentInstanceSymbol = taggingResolver.<ExpandedComponentInstanceSymbol>resolve("tests.a.compA", ExpandedComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
TagHelper.resolveTags(taggingResolver, componentInstanceSymbol);
MasterGenerator masterGenerator = new MasterGenerator();
masterGenerator.setGenerationTargetPath("./target/generated-sources/basicGeneration/");
......@@ -34,6 +42,7 @@ public class GenerationTest extends AbstractSymtabTest {
ExpandedComponentInstanceSymbol componentInstanceSymbol = taggingResolver.<ExpandedComponentInstanceSymbol>resolve("tests.a.compA", ExpandedComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
TagHelper.resolveTags(taggingResolver, componentInstanceSymbol);
MasterGenerator masterGenerator = new CMakeMasterGenerator();
masterGenerator.setGenerationTargetPath("./target/generated-sources/CMakeGeneration/");
......@@ -50,6 +59,7 @@ public class GenerationTest extends AbstractSymtabTest {
ExpandedComponentInstanceSymbol componentInstanceSymbol = taggingResolver.<ExpandedComponentInstanceSymbol>resolve("tests.a.addComp", ExpandedComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
TagHelper.resolveTags(taggingResolver, componentInstanceSymbol);
MasterGenerator masterGenerator = new MiddlewareMasterGenerator();
masterGenerator.setGenerationTargetPath("./target/generated-sources/middlewareMasterGenerator/src/");
......@@ -58,7 +68,23 @@ public class GenerationTest extends AbstractSymtabTest {
masterGenerator.add(new DummyMiddlewareGenerator(), "dummy");
masterGenerator.generate(componentInstanceSymbol, taggingResolver);
}
@Test
public void testDistributedTargetGenerator() throws IOException {
TaggingResolver taggingResolver = createSymTabAndTaggingResolver("src/test/resources/");
RosToEmamTagSchema.registerTagTypes(taggingResolver);
ExpandedComponentInstanceSymbol componentInstanceSymbol = taggingResolver.<ExpandedComponentInstanceSymbol>resolve("tests.dist.distComp", ExpandedComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
TagHelper.resolveTags(taggingResolver, componentInstanceSymbol);
MasterGenerator masterGenerator = new DistributedTargetGenerator("./target/generated-sources/distributed/src/");
masterGenerator.add(new CPPImpl(), "cpp");
masterGenerator.add(new RosCppImpl(), "roscpp");
masterGenerator.generate(componentInstanceSymbol, taggingResolver);
}
}
package tests.dist;
component DistComp{
component SubComp1{
ports out Q out1,
out Q out2;
}
component SubComp2{
ports in Q in1,
in Q in2;
}
instance SubComp1 sub1;
instance SubComp2 sub2;
connect sub1.out1 -> sub2.in1;
connect sub1.out2 -> sub2.in2;
}
\ No newline at end of file
package tests.dist;
conforms to de.monticore.lang.monticar.generator.roscpp.RosToEmamTagSchema;
tags SimpleDist{
tag distComp.sub1.out1 with RosConnection = {topic = (topicIn1, std_msgs/Float64), msgField = data};
tag distComp.sub1.out2 with RosConnection = {topic = (topicIn2, std_msgs/Float64), msgField = data};
tag distComp.sub2.in1 with RosConnection = {topic = (topicIn1, std_msgs/Float64), msgField = data};
tag distComp.sub2.in2 with RosConnection = {topic = (topicIn2, std_msgs/Float64), msgField = data};
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment