diff --git a/core/build.gradle b/core/build.gradle index 8c773f5..d09c336 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -53,5 +53,7 @@ micronaut { } } - - +test { + // Avoid errors from PlantUML tests looking for an X library, by using AWT in headless mode + jvmArgs '-Djava.awt.headless=true' +} \ No newline at end of file diff --git a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/ModelLoader.java b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/ModelLoader.java index 1ee12c2..4f6c71b 100644 --- a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/ModelLoader.java +++ b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/ModelLoader.java @@ -37,6 +37,19 @@ public InMemoryEmfModel getInMemoryFlexmiModel(String flexmi, String emfatic) th model.setName("M"); return model; } + + public InMemoryEmfModel getInMemoryXmiModel(String xmi, String emfatic) throws Exception { + ResourceSet resourceSet = new ResourceSetImpl(); + EPackage ePackage = getEPackage(emfatic); + resourceSet.getPackageRegistry().put(ePackage.getNsURI(), ePackage); + resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new XMIResourceFactoryImpl()); + Resource resource = resourceSet.createResource(URI.createURI("xmi.xmi")); + resource.load(new ByteArrayInputStream(xmi.getBytes()), null); + + InMemoryEmfModel model = new InMemoryEmfModel(resource); + model.setName("M"); + return model; + } public InMemoryEmfModel getBlankInMemoryModel(String emfatic) throws Exception { ResourceSet resourceSet = new ResourceSetImpl(); diff --git a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonController.java b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonController.java index 5f54fcb..727bc01 100644 --- a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonController.java +++ b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonController.java @@ -112,8 +112,14 @@ protected void runEml(EmlModule module, RunEpsilonRequest request, EpsilonExecut Model leftModel = getFirstModel(request); leftModel.setName("Left"); leftModel.getAliases().add("Source"); - - InMemoryEmfModel rightModel = loader.getInMemoryFlexmiModel(request.getThirdFlexmi(), request.getThirdEmfatic()); + + InMemoryEmfModel rightModel; + // The MDENet EP and Playground originally sent "undefined" as default value across all parameters + if (request.getXmi() != null && !"undefined".equals(request.getXmi())) { + rightModel = loader.getInMemoryXmiModel(request.getThirdXmi(), request.getThirdEmfatic()); + } else { + rightModel = loader.getInMemoryFlexmiModel(request.getThirdFlexmi(), request.getThirdEmfatic()); + } rightModel.setName("Right"); rightModel.getAliases().add("Source"); @@ -233,7 +239,9 @@ protected void runEol(EolModule module, RunEpsilonRequest request) throws Except protected Model getFirstModel(RunEpsilonRequest request) throws Exception { // The MDENet EP and Playground originally sent "undefined" as default value across all parameters - if (request.getFlexmi() != null && !"undefined".equals(request.getFlexmi())) { + if (request.getXmi() != null && !"undefined".equals(request.getXmi())) { + return loader.getInMemoryXmiModel(request.getXmi(), request.getEmfatic()); + } else if (request.getFlexmi() != null && !"undefined".equals(request.getFlexmi())) { return loader.getInMemoryFlexmiModel(request.getFlexmi(), request.getEmfatic()); } else if (request.getJson() != null && !"undefined".equals(request.getJson())) { return loader.getInMemoryJsonModel(request.getJson()); diff --git a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonRequest.java b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonRequest.java index c713e58..b41e488 100644 --- a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonRequest.java +++ b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonRequest.java @@ -12,13 +12,13 @@ public class RunEpsilonRequest { @NotBlank private String program; - private String flexmi; + private String flexmi, xmi; private String emfatic; private String json; - private String secondProgram, secondFlexmi, secondEmfatic; + private String secondProgram, secondFlexmi, secondXmi, secondEmfatic; - private String thirdFlexmi, thirdEmfatic; + private String thirdFlexmi, thirdXmi, thirdEmfatic; public String getLanguage() { return language; @@ -43,7 +43,15 @@ public String getFlexmi() { public void setFlexmi(String flexmi) { this.flexmi = flexmi; } + + public String getXmi() { + return xmi; + } + public void setXmi(String xmi) { + this.xmi = xmi; + } + public String getEmfatic() { return emfatic; } @@ -67,6 +75,14 @@ public String getSecondFlexmi() { public void setSecondFlexmi(String secondFlexmi) { this.secondFlexmi = secondFlexmi; } + + public String getSecondXmi() { + return secondXmi; + } + + public void setSecondXmi(String secondXmi) { + this.secondXmi = secondXmi; + } public String getSecondEmfatic() { return secondEmfatic; @@ -84,6 +100,14 @@ public void setThirdFlexmi(String thirdFlexmi) { this.thirdFlexmi = thirdFlexmi; } + public String getThirdXmi() { + return thirdXmi; + } + + public void setThirdXmi(String thirdXmi) { + this.thirdXmi = thirdXmi; + } + public String getThirdEmfatic() { return thirdEmfatic; } diff --git a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplate.java b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplate.java index 0b11915..3d27b53 100644 --- a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplate.java +++ b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplate.java @@ -13,9 +13,8 @@ public class StringGeneratingTemplate extends EglFileGeneratingTemplate { protected Map results = null; - public StringGeneratingTemplate(EglTemplateSpecification spec, IEglContext context, URI outputRoot, Map results, String templateCode) - throws Exception { - super(new StringGeneratingTemplateSpecification(templateCode), context, outputRoot); + public StringGeneratingTemplate(EglTemplateSpecification spec, IEglContext context, URI outputRoot, Map results, String templateCode) throws Exception { + super(spec, context, outputRoot); this.results = results; } diff --git a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplateFactory.java b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplateFactory.java index 23c8f49..524f248 100644 --- a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplateFactory.java +++ b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplateFactory.java @@ -16,7 +16,8 @@ public class StringGeneratingTemplateFactory extends EglTemplateFactory { @Override public EglTemplate load(URI resource) throws EglRuntimeException { try { - return new StringGeneratingTemplate(new StringGeneratingTemplateSpecification(templateCode), context, resource, results, templateCode); + StringGeneratingTemplateSpecification spec = new StringGeneratingTemplateSpecification(templateCode, getImportManager()); + return new StringGeneratingTemplate(spec, context, resource, results, templateCode); } catch (Exception e) { throw new EglRuntimeException(e); } diff --git a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplateSpecification.java b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplateSpecification.java index 1a16d66..d1e7767 100644 --- a/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplateSpecification.java +++ b/core/src/main/java/org/eclipse/epsilon/labs/playground/fn/run/egl/StringGeneratingTemplateSpecification.java @@ -9,13 +9,14 @@ import org.eclipse.epsilon.egl.internal.IEglModule; import org.eclipse.epsilon.egl.spec.EglTemplateSpecification; import org.eclipse.epsilon.egl.traceability.Template; +import org.eclipse.epsilon.eol.IImportManager; public class StringGeneratingTemplateSpecification extends EglTemplateSpecification { private final String code; - protected StringGeneratingTemplateSpecification(String code) { - super("Anonymous", new NullFormatter(), new IncrementalitySettings(), Collections.emptyList()); + protected StringGeneratingTemplateSpecification(String code, IImportManager importManager) { + super("Anonymous", new NullFormatter(), new IncrementalitySettings(), importManager, Collections.emptyList()); this.code = code; } diff --git a/core/src/test/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonTest.java b/core/src/test/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonTest.java index e499039..7baf216 100644 --- a/core/src/test/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonTest.java +++ b/core/src/test/java/org/eclipse/epsilon/labs/playground/fn/run/RunEpsilonTest.java @@ -1,10 +1,18 @@ package org.eclipse.epsilon.labs.playground.fn.run; +import static org.junit.Assert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + import org.junit.jupiter.api.Test; +import org.junit.matchers.JUnitMatchers; + +import com.google.common.io.CharStreams; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import jakarta.inject.Inject; @@ -30,4 +38,49 @@ public void egx() { assertEquals(2, response.getGeneratedFiles().size()); } + @Test + public void egxInputXmi() { + var req = new RunEpsilonRequest(); + req.setLanguage("egx"); + req.setProgram("rule T2T transform t : Tree { template : 'foo.egl' target: t.name + '.txt'}"); + req.setSecondProgram("Tree [%=t.name%]"); + req.setXmi("\n" + + "\n" + + " \n" + + " \n" + + "\n" + + ""); + req.setEmfatic("package tree; class Tree { attr String name; }"); + + var response = client.execute(req); + assertNull(response.getError()); + assertNotNull(response.getGeneratedFiles()); + assertEquals(2, response.getGeneratedFiles().size()); + } + + @Test + public void emlSecondInputXmi() throws Exception { + var req = new RunEpsilonRequest(); + req.setLanguage("eml"); + req.setProgram(getResourceAsString("/eml/tree.eml")); + req.setSecondProgram(getResourceAsString("/eml/tree.ecl")); + req.setXmi(getResourceAsString("/eml/left.xmi")); + req.setThirdXmi(getResourceAsString("/eml/right.xmi")); + + String emfaticSource = getResourceAsString("/eml/tree.emf"); + req.setEmfatic(emfaticSource); + req.setSecondEmfatic(emfaticSource); + req.setThirdEmfatic(emfaticSource); + + var response = client.execute(req); + assertNull(response.getError()); + assertThat(response.getTargetModelDiagram(), JUnitMatchers.containsString("A")); + assertThat(response.getTargetModelDiagram(), JUnitMatchers.containsString("B")); + } + + private String getResourceAsString(String resource) throws IOException { + var inputStream = getClass().getResourceAsStream(resource); + return CharStreams.toString(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + } + } diff --git a/core/src/test/resources/eml/left.xmi b/core/src/test/resources/eml/left.xmi new file mode 100644 index 0000000..8988d2c --- /dev/null +++ b/core/src/test/resources/eml/left.xmi @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/core/src/test/resources/eml/right.xmi b/core/src/test/resources/eml/right.xmi new file mode 100644 index 0000000..5edf56c --- /dev/null +++ b/core/src/test/resources/eml/right.xmi @@ -0,0 +1,4 @@ + + + + diff --git a/core/src/test/resources/eml/tree.ecl b/core/src/test/resources/eml/tree.ecl new file mode 100644 index 0000000..254faac --- /dev/null +++ b/core/src/test/resources/eml/tree.ecl @@ -0,0 +1,7 @@ +// We match persons by name +rule NodeWithNode + match l : Left!Node + with r : Right!Node { + + compare: l.label = r.label +} \ No newline at end of file diff --git a/core/src/test/resources/eml/tree.emf b/core/src/test/resources/eml/tree.emf new file mode 100644 index 0000000..e80db5f --- /dev/null +++ b/core/src/test/resources/eml/tree.emf @@ -0,0 +1,7 @@ +@namespace(uri="tree", prefix="") +package tree; + +class Node { + attr String label; + val Node[*] children; +} \ No newline at end of file diff --git a/core/src/test/resources/eml/tree.eml b/core/src/test/resources/eml/tree.eml new file mode 100644 index 0000000..acf5112 --- /dev/null +++ b/core/src/test/resources/eml/tree.eml @@ -0,0 +1,19 @@ +rule NodeWithNode + merge l: Left!Node + with r: Right!Node + into m: Merged!Node { + m.label = l.label; + + var mergedChildren: Set; + mergedChildren.addAll(l.children.equivalent()); + mergedChildren.addAll(r.children.equivalent()); + m.children.addAll(mergedChildren); +} + +rule NodeFromNode + transform s: Source!Node + to t: Target!Node +{ + t.label = s.label; + t.children ::= s.children; +} \ No newline at end of file diff --git a/http-server/src/main/resources/mdenet_tool.egl b/http-server/src/main/resources/mdenet_tool.egl index f6735b0..50de8cf 100644 --- a/http-server/src/main/resources/mdenet_tool.egl +++ b/http-server/src/main/resources/mdenet_tool.egl @@ -38,16 +38,19 @@ {"name":"secondProgram", "type":"etl"}, {"name":"emfatic", "type":"emfatic"}, {"name":"flexmi", "type":"flexmi", "instanceOf": "emfatic"}, + {"name":"xmi", "type":"xmi", "instanceOf": "emfatic"}, {"name":"json", "type":"json"}, {"name":"secondEmfatic", "type":"emfatic"}, {"name":"secondFlexmi", "type":"flexmi", "instanceOf": "secondEmfatic"}, + {"name":"secondXmi", "type":"xmi", "instanceOf": "secondEmfatic"}, {"name":"thirdEmfatic", "type":"emfatic"}, - {"name":"thirdFlexmi", "type":"flexmi", "instanceOf": "thirdEmfatic"} + {"name":"thirdFlexmi", "type":"flexmi", "instanceOf": "thirdEmfatic"}, + {"name":"thirdXmi", "type":"xmi", "instanceOf": "thirdEmfatic"} ], "returnType": "text", "path": "[%= urls.get("epsilon") %]" }, - + { "id": "function-egl", "name": "egl",