diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 98296c70f5cbef287ac6e7c45c1414cc40eb7528..b981616c4981e4c033e07cc56d3c75fbfc63cf0d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,10 +1,22 @@ stages: -- linux +- project +- adapter -BranchJobLinux: - stage: linux +BranchJobProject: + stage: project image: registry.git.rwth-aachen.de/monticore/embeddedmontiarc/generators/emam2someip script: - mvn clean install -s settings.xml except: - master + +BranchJobAdapter: + stage: adapter + image: registry.git.rwth-aachen.de/monticore/embeddedmontiarc/generators/emam2someip + script: + - cd someip_adapter + - cmake . + - make + except: + - master + diff --git a/pom.xml b/pom.xml index e415b1f698e491e46e6147f3da19ebd6d15dca7a..00e4a61b9c374fb563b869bb0fcc519f11d81aaf 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ embedded-montiarc 0.1.10-SNAPSHOT - + de.se_rwth.commons diff --git a/src/main/java/de/monticore/lang/monticar/generator/someip/GeneratorSomeIP.java b/src/main/java/de/monticore/lang/monticar/generator/someip/GeneratorSomeIP.java new file mode 100755 index 0000000000000000000000000000000000000000..34611b2edebeca4959e84308da03ee16fb2e1a13 --- /dev/null +++ b/src/main/java/de/monticore/lang/monticar/generator/someip/GeneratorSomeIP.java @@ -0,0 +1,52 @@ +package de.monticore.lang.monticar.generator.someip; + +import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol; +import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol; +//import de.monticore.lang.embeddedmontiarc.tagging.middleware.someip.SomeIPConnectionSymbol; +import de.monticore.lang.monticar.generator.someip.template.SomeIPAdapterModel; +import de.monticore.lang.monticar.generator.someip.template.SomeIPTemplates; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class GeneratorSomeIP { + + List generateSomeIPAdapter(EMAComponentInstanceSymbol component) { + List files = new ArrayList<>(); + + // Get info about the ports from the component + Collection ports = component.getPortInstanceList(); + + // Create and fill model + SomeIPAdapterModel model = new SomeIPAdapterModel(component.getFullName()); + + model.addPorts(ports); + + //Generate files and write to project + String content = SomeIPTemplates.generateSomeIPAdapter(model); + + File file = new File("./target/generated-sources/ports.txt"); + files.add(file); + + FileWriter fr = null; + try { + fr = new FileWriter(file); + fr.write(content); + } catch (IOException e) { + e.printStackTrace(); + } finally { + //Close resources + try { + fr.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return files; + } + +} diff --git a/src/main/java/de/monticore/lang/monticar/generator/someip/template/SomeIPAdapterModel.java b/src/main/java/de/monticore/lang/monticar/generator/someip/template/SomeIPAdapterModel.java new file mode 100644 index 0000000000000000000000000000000000000000..09b72c34d16a4ad47cbaf90544217e12d4dba484 --- /dev/null +++ b/src/main/java/de/monticore/lang/monticar/generator/someip/template/SomeIPAdapterModel.java @@ -0,0 +1,49 @@ +package de.monticore.lang.monticar.generator.someip.template; + +import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol; +import de.monticore.lang.embeddedmontiarc.tagging.middleware.MiddlewareSymbol; +import de.monticore.lang.embeddedmontiarc.tagging.middleware.someip.SomeIPConnectionSymbol; +import de.monticore.lang.embeddedmontiarc.tagging.middleware.someip.SomeIPConnectionSymbol.SomeIPConnectionKind; + +import java.util.*; + +// Used to fill .ftl files + +public class SomeIPAdapterModel { + + private String compName; + private List ports = new ArrayList<>(); + + public SomeIPAdapterModel(String compName) { + this.compName = compName; + } + + public String getCompName() { + return compName; + } + + // Parse through component to find information about its ports + public void addPorts(Collection ports) + { + for (EMAPortInstanceSymbol port : ports) + { + String kind = port.isIncoming()?"incoming":"outgoing"; + String symbolKind = "unknown symbol"; + Optional symbol = port.getMiddlewareSymbol(); + if(symbol.isPresent() && symbol.get().isKindOf(SomeIPConnectionKind.INSTANCE)) + { + SomeIPConnectionSymbol sym = (SomeIPConnectionSymbol) symbol.get(); + String topicName = sym.getTopicName().isPresent()?sym.getTopicName().get():"unknown"; + symbolKind = "someip, topic: "+topicName; + } + + this.ports.add(port.getName()+" : "+kind+" ("+symbolKind+")"); + } + } + + public List getPorts() + { + return this.ports; + } + +} diff --git a/src/main/java/de/monticore/lang/monticar/generator/someip/template/SomeIPTemplates.java b/src/main/java/de/monticore/lang/monticar/generator/someip/template/SomeIPTemplates.java new file mode 100755 index 0000000000000000000000000000000000000000..cfa8b9b8b5a4bdded845000bbd99277a9cb4c3d8 --- /dev/null +++ b/src/main/java/de/monticore/lang/monticar/generator/someip/template/SomeIPTemplates.java @@ -0,0 +1,53 @@ +package de.monticore.lang.monticar.generator.someip.template; + +import de.se_rwth.commons.logging.Log; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +public class SomeIPTemplates { + + private static final Template SOMEIP_PRETTYPRINT; + + // Loading .ftl files + static { + Configuration conf = new Configuration(Configuration.VERSION_2_3_23); + conf.setDefaultEncoding("UTF-8"); + conf.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER); + conf.setLogTemplateExceptions(false); + conf.setClassForTemplateLoading(SomeIPTemplates.class, ""); + try { + SOMEIP_PRETTYPRINT = conf.getTemplate("PrettyPrint.ftl"); + } catch (IOException e) { + String msg = "could not load template"; + Log.error(msg, e); + throw new RuntimeException(msg, e); + } + } + + public static String generateSomeIPAdapter(SomeIPAdapterModel model) { + HashMap data = new HashMap<>(); + data.put("model", model); + return generate(SOMEIP_PrettyPrint, data); + } + + + @SuppressWarnings("rawtypes") + private static String generate(Template template, Map dataForTemplate) { + Log.errorIfNull(template); + Log.errorIfNull(dataForTemplate); + StringWriter sw = new StringWriter(); + try { + template.process(dataForTemplate, sw); + } catch (TemplateException | IOException e) { + Log.error("template generation failed, template: " + template.getName(), e); + } + return sw.toString(); + } +} diff --git a/src/main/java/emam2someipgroup/App.java b/src/main/java/emam2someipgroup/App.java deleted file mode 100644 index 3be1b4c6455938b18374e678d381d5d5cbd16fbf..0000000000000000000000000000000000000000 --- a/src/main/java/emam2someipgroup/App.java +++ /dev/null @@ -1,13 +0,0 @@ -package emam2someipgroup; - -/** - * Hello world! - * - */ -public class App -{ - public static void main( String[] args ) - { - System.out.println( "Hello World!" ); - } -} diff --git a/src/main/resources/de/monticore/lang/monticar/generator/mqtt/template/PrettyPrint.ftl b/src/main/resources/de/monticore/lang/monticar/generator/mqtt/template/PrettyPrint.ftl new file mode 100644 index 0000000000000000000000000000000000000000..71033724724222d8f6e3f0b4f094a668c7ff4688 --- /dev/null +++ b/src/main/resources/de/monticore/lang/monticar/generator/mqtt/template/PrettyPrint.ftl @@ -0,0 +1,9 @@ +<#--@formatter:off--> + +Component name: ${model.getCompName()} + +Ports: + +<#list model.getPorts() as gen> +${gen} + diff --git a/src/test/java/de/monticore/lang/monticar/generator/someip/AbstractSymtabTest.java b/src/test/java/de/monticore/lang/monticar/generator/someip/AbstractSymtabTest.java new file mode 100644 index 0000000000000000000000000000000000000000..050d2b56bc49a0afd140179c21b8001b99472d8e --- /dev/null +++ b/src/test/java/de/monticore/lang/monticar/generator/someip/AbstractSymtabTest.java @@ -0,0 +1,154 @@ +package de.monticore.lang.monticar.generator.someip; + +/* + * Copyright (c) 2015 RWTH Aachen. All rights reserved. + * + * http://www.se-rwth.de/ + */ + +import de.monticore.ModelingLanguageFamily; +import de.monticore.io.paths.ModelPath; +import de.monticore.lang.embeddedmontiarc.LogConfig; +import de.monticore.lang.embeddedmontiarc.embeddedmontiarcmath._symboltable.EmbeddedMontiArcMathLanguage; +import de.monticore.lang.embeddedmontiarc.tagging.middleware.ros.RosToEmamTagSchema; +import de.monticore.lang.monticar.Utils; +import de.monticore.lang.monticar.enumlang._symboltable.EnumLangLanguage; +import de.monticore.lang.monticar.streamunits._symboltable.StreamUnitsLanguage; +import de.monticore.lang.monticar.struct._symboltable.StructLanguage; +import de.monticore.lang.tagging._symboltable.TaggingResolver; +import de.monticore.symboltable.GlobalScope; +import de.monticore.symboltable.Scope; +import org.junit.Assert; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertTrue; + +/** + * Common methods for symboltable tests + */ +public class AbstractSymtabTest { + + public AbstractSymtabTest() { + } + + public static TaggingResolver createSymTabAndTaggingResolver(String... modelPath) { + Scope scope = createSymTab(modelPath); + TaggingResolver taggingResolver = new TaggingResolver(scope, Arrays.asList(modelPath)); + RosToEmamTagSchema.registerTagTypes(taggingResolver); + return taggingResolver; + } + + public static Scope createSymTab(String... modelPath) { + ModelingLanguageFamily fam = new ModelingLanguageFamily(); + EmbeddedMontiArcMathLanguage montiArcLanguage = new EmbeddedMontiArcMathLanguage(); + fam.addModelingLanguage(montiArcLanguage); + fam.addModelingLanguage(new StreamUnitsLanguage()); + fam.addModelingLanguage(new StructLanguage()); + fam.addModelingLanguage(new EnumLangLanguage()); + ModelPath mp = new ModelPath(new Path[0]); + String[] var4 = modelPath; + int var5 = modelPath.length; + + for(int var6 = 0; var6 < var5; ++var6) { + String m = var4[var6]; + mp.addEntry(Paths.get(m)); + } + + LogConfig.init(); + GlobalScope scope = new GlobalScope(mp, fam); + Utils.addBuiltInTypes(scope); + return scope; + } + + public static void testFilesAreEqual(List files, String restPath) { + assertTrue(files.size() > 0); + for (File f : files) { + File fileTarget = new File("./src/test/resources/results/" + restPath + f.getName()); +// System.out.println("" + fileTarget.exists() + "Exists:"); +// System.out.println(f.getName() + " " + fileTarget.getName() + "Comparing:"); + assertTrue(areBothFilesEqual(f, fileTarget)); + } + } + + public static void testFilesAreEqual(List files, String relResultPath, String basePath) { + String resultPath = "src/test/resources/results/"; + for (File f : files) { + File tmpFile = new File(basePath); + String relativePath = f.getAbsolutePath().replace(tmpFile.getAbsolutePath(), ""); + File fileTarget = new File(resultPath + relResultPath + relativePath); + assertTrue(areBothFilesEqual(f, fileTarget)); + } + + + } + + public static boolean areBothFilesEqual(File file1, File file2) { + if (!file1.exists()) { + Assert.fail("file does not exist: " + file1.getAbsolutePath()); + return false; + } + if (!file2.exists()) { + Assert.fail("file does not exist: " + file2.getAbsolutePath()); + return false; + } + List lines1; + List lines2; + try { + lines1 = Files.readAllLines(file1.toPath()); + lines2 = Files.readAllLines(file2.toPath()); + } catch (IOException e) { + e.printStackTrace(); + Assert.fail("IO error: " + e.getMessage()); + return false; + } + lines1 = discardEmptyLines(lines1); + lines1 = discardCommentLines(lines1); + lines2 = discardEmptyLines(lines2); + lines2 = discardCommentLines(lines2); + if (lines1.size() != lines2.size()) { + Assert.fail( + "files have different number of lines: " + + file1.getAbsolutePath() + + " has " + lines1.size() + + " lines and " + file2.getAbsolutePath() + " has " + lines2.size() + " lines" + ); + return false; + } + int len = lines1.size(); + for (int i = 0; i < len; i++) { + String l1 = lines1.get(i); + String l2 = lines2.get(i); + Assert.assertEquals("files differ in " + i + " line: " + + file1.getAbsolutePath() + + " has " + l1 + + " and " + file2.getAbsolutePath() + " has " + l2, + l1, + l2 + ); + } + return true; + } + + private static List discardEmptyLines(List lines) { + return lines.stream() + .map(String::trim) + .filter(l -> !l.isEmpty()) + .collect(Collectors.toList()); + } + + private static List discardCommentLines(List lines) { + return lines.stream() + .map(String::trim) + .filter(l -> !l.startsWith("//")) + .collect(Collectors.toList()); + } +} + diff --git a/src/test/java/de/monticore/lang/monticar/generator/someip/PrettyPrintGenerationTest.java b/src/test/java/de/monticore/lang/monticar/generator/someip/PrettyPrintGenerationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..af498bca078ffd1947896617d5c767ba54b0c46f --- /dev/null +++ b/src/test/java/de/monticore/lang/monticar/generator/someip/PrettyPrintGenerationTest.java @@ -0,0 +1,41 @@ +package de.monticore.lang.monticar.generator.someip; + +import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol; +import de.monticore.lang.embeddedmontiarc.tagging.middleware.ros.RosToEmamTagSchema; +import de.monticore.lang.tagging._symboltable.TaggingResolver; +import de.monticore.lang.embeddedmontiarc.tagging.middleware.someip.SomeIPConnectionSymbol; + +import static org.junit.Assert.assertNotNull; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.junit.Test; + +public class PrettyPrintGenerationTest extends AbstractSymtabTest { + + @Test + public void testPrettyPrint() throws IOException { + + TaggingResolver taggingResolver = createSymTabAndTaggingResolver("src/test/resources/"); + + // Ros schema is used for now + RosToEmamTagSchema.registerTagTypes(taggingResolver); + + // Create component instance and run the generator + EMAComponentInstanceSymbol componentInstanceSymbol = taggingResolver.resolve("tests.a.compA", EMAComponentInstanceSymbol.KIND).orElse(null); + + assertNotNull(componentInstanceSymbol); + + GeneratorSomeIP generatorSomeIP = new GeneratorSomeIP(); + + // Connect component's ports to topics + componentInstanceSymbol.getPortInstance("portA").orElse(null).setMiddlewareSymbol(new SomeIPConnectionSymbol(1,2,3)); + + List files = generatorSomeIP.generatePrettyPrint(componentInstanceSymbol); + + //testFilesAreEqual(files, ""); + } + +} diff --git a/src/test/java/emam2someipgroup/AppTest.java b/src/test/java/emam2someipgroup/AppTest.java deleted file mode 100644 index 9d911f161f8779e8180520d9542de9513e6787cc..0000000000000000000000000000000000000000 --- a/src/test/java/emam2someipgroup/AppTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package emam2someipgroup; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest -{ - /** - * Rigorous Test :-) - */ - @Test - public void shouldAnswerWithTrue() - { - assertTrue( true ); - } -} diff --git a/src/test/resources/results/echo/ports.txt b/src/test/resources/results/echo/ports.txt new file mode 100644 index 0000000000000000000000000000000000000000..2596773cae288513485314df090bcc38b57b6988 --- /dev/null +++ b/src/test/resources/results/echo/ports.txt @@ -0,0 +1,9 @@ + +Component name: tests.a.compA + +Ports: + +portA : incoming (mqtt, topic: /clock) +portB : incoming (unknown symbol) +portC : outgoing (unknown symbol) +portD : outgoing (unknown symbol) diff --git a/src/test/resources/tests/a/CompA.emam b/src/test/resources/tests/a/CompA.emam new file mode 100644 index 0000000000000000000000000000000000000000..fa3dcaa9238219b889ef10eb21cfd7fda19f497e --- /dev/null +++ b/src/test/resources/tests/a/CompA.emam @@ -0,0 +1,12 @@ +package tests.a; + +component CompA{ + port in Q portA; + port in Q portB; + port out Q portC; + port out Q portD; + + implementation Math{ + portA = portD; + } +}