Pushed support for EGL templates in Flexmi
diff --git a/examples/org.eclipse.epsilon.examples.flexmi.comps/library.flexmi b/examples/org.eclipse.epsilon.examples.flexmi.comps/library.flexmi
index dfa3663..da21f77 100644
--- a/examples/org.eclipse.epsilon.examples.flexmi.comps/library.flexmi
+++ b/examples/org.eclipse.epsilon.examples.flexmi.comps/library.flexmi
@@ -11,4 +11,20 @@
</comp>
</content>
</_template>
+
+ <_template name="nary_operator">
+ <parameter name="n"/>
+ <parameter name="in"/>
+ <parameter name="out"/>
+ <content language="EGL">
+ <![CDATA[
+ <comp>
+ [%for (i in 1.to(n.asInteger())){%]
+ <in name="in[%=i%]" type="${in}"/>
+ [%}%]
+ <out name="result" type="${out}"/>
+ </comp>
+ ]]>
+ </content>
+ </_template>
</_>
\ No newline at end of file
diff --git a/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-limit-calculator.flexmi b/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-limit-calculator.flexmi
index 128abbb..f3735f2 100644
--- a/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-limit-calculator.flexmi
+++ b/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-limit-calculator.flexmi
@@ -14,8 +14,8 @@
<out name="speedLimit" type="float"/>
</comp>
- <_binary_operator name="Max" action="result = in1 > in2 ? in1 : in2"
- _in="float" _out="float"/>
+ <_nary_operator name="Max" action="result = in1 > in2 ? in1 : in2"
+ _in="float" _out="float" _n="2"/>
<con from="${this}.location" to="${this}.SpeedLimitDatastore.location"/>
<con from="${this}.SpeedLimitDatastore.speedLimit" to="${this}.Max.in1"/>
diff --git a/plugins/org.eclipse.epsilon.flexmi/META-INF/MANIFEST.MF b/plugins/org.eclipse.epsilon.flexmi/META-INF/MANIFEST.MF
index 7206570..57f69df 100644
--- a/plugins/org.eclipse.epsilon.flexmi/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.epsilon.flexmi/META-INF/MANIFEST.MF
@@ -7,6 +7,10 @@
Require-Bundle: org.eclipse.emf.ecore;visibility:=reexport,
org.eclipse.emf.ecore.xmi,
com.google.guava,
- org.apache.commons.lang3
+ org.apache.commons.lang3,
+ org.eclipse.epsilon.eol.engine,
+ org.eclipse.epsilon.egl.engine,
+ org.eclipse.epsilon.emc.plainxml
Export-Package: org.eclipse.epsilon.flexmi,
+ org.eclipse.epsilon.flexmi.templates,
org.eclipse.epsilon.flexmi.xml
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/FlexmiResource.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/FlexmiResource.java
index c733288..36ab38f 100644
--- a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/FlexmiResource.java
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/FlexmiResource.java
@@ -39,6 +39,7 @@
import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+import org.eclipse.epsilon.flexmi.templates.Template;
import org.eclipse.epsilon.flexmi.xml.Location;
import org.eclipse.epsilon.flexmi.xml.PseudoSAXParser;
import org.eclipse.epsilon.flexmi.xml.PseudoSAXParser.Handler;
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/Template.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/Template.java
deleted file mode 100644
index 2804d58..0000000
--- a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/Template.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2008 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.flexmi;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.text.StrLookup;
-import org.apache.commons.lang3.text.StrSubstitutor;
-import org.eclipse.epsilon.flexmi.xml.Xml;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-public class Template {
-
- protected String name;
- protected ArrayList<String> parameters = new ArrayList<String>();
- protected Element content;
-
- public static final String NODE_NAME = "_template";
- public static final String PREFIX = "_";
-
- public Template(Element element) {
- this.name = element.getAttribute("name");
- for (Element parameterElement : Xml.getChildren(element, "parameter")) {
- parameters.add(parameterElement.getAttribute("name"));
- }
- content = Xml.getChild(element, "content");
- }
-
- public String getName() {
- return name;
- }
-
- public ArrayList<String> getParameters() {
- return parameters;
- }
-
- public Element getContent() {
- return content;
- }
-
- public List<Element> apply(Node node) {
-
- Element call = (Element) node;
- List<Element> application = new ArrayList<Element>();
- for (Element contentChild : Xml.getChildren(content)) {
- application.add((Element) contentChild.cloneNode(true));
- }
-
- for (Element applicationElement : application) {
- for (String attributeName : Xml.getAttributeNames(call)) {
- if (!attributeName.startsWith(Template.PREFIX)) {
- applicationElement.setAttribute(attributeName, call.getAttribute(attributeName));
- }
- }
- replaceParameters(applicationElement, call);
- }
-
- return application;
- }
-
- protected void replaceParameters(Element element, Element call) {
-
- StrSubstitutor substitutor = new StrSubstitutor(new StrLookup<String>() {
- @Override
- public String lookup(String name) {
- return call.getAttribute("_" + name);
- }
- });
-
- for (Node attribute : Xml.getAttributes(element)) {
- if (attribute.getNodeValue().indexOf("$") > -1) {
- attribute.setNodeValue(substitutor.replace(attribute.getNodeValue()));
- }
- }
-
- for (Element child : Xml.getChildren(element)) {
- replaceParameters(child, call);
- }
-
- }
-
-}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/EglTemplate.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/EglTemplate.java
new file mode 100644
index 0000000..68bdfa4
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/EglTemplate.java
@@ -0,0 +1,44 @@
+package org.eclipse.epsilon.flexmi.templates;
+
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.eclipse.epsilon.egl.EglTemplateFactory;
+import org.eclipse.epsilon.egl.EglTemplateFactoryModuleAdapter;
+import org.eclipse.epsilon.emc.plainxml.StringInputStream;
+import org.eclipse.epsilon.eol.execute.context.Variable;
+import org.eclipse.epsilon.flexmi.xml.Xml;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class EglTemplate extends XmlTemplate {
+
+ public EglTemplate(Element element) {
+ super(element);
+ }
+
+ @Override
+ public List<Element> getApplication(Element call) {
+ try {
+ EglTemplateFactoryModuleAdapter module = new EglTemplateFactoryModuleAdapter(new EglTemplateFactory());
+ module.parse(content.getTextContent());
+
+ for (String parameter : getParameters()) {
+ module.getContext().getFrameStack().put(Variable.createReadOnlyVariable(parameter, call.getAttribute(Template.PREFIX + parameter)));
+ }
+
+ String xml = "<?xml version=\"1.0\"?><root>" + (module.execute() + "").trim() + "</root>";
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ Document document = documentBuilder.parse(new StringInputStream(xml));
+ return Xml.getChildren(document.getDocumentElement());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/Template.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/Template.java
new file mode 100644
index 0000000..e516b07
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/Template.java
@@ -0,0 +1,52 @@
+/*********************************************************************
+* Copyright (c) 2008 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.flexmi.templates;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.text.StrLookup;
+import org.apache.commons.lang3.text.StrSubstitutor;
+import org.eclipse.epsilon.flexmi.xml.Xml;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public abstract class Template {
+
+ protected String name;
+ protected ArrayList<String> parameters = new ArrayList<String>();
+ protected Element content;
+
+ public static final String NODE_NAME = "_template";
+ public static final String PREFIX = "_";
+
+ public Template(Element element) {
+ this.name = element.getAttribute("name");
+ for (Element parameterElement : Xml.getChildren(element, "parameter")) {
+ parameters.add(parameterElement.getAttribute("name"));
+ }
+ content = Xml.getChild(element, "content");
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ArrayList<String> getParameters() {
+ return parameters;
+ }
+
+ public Element getContent() {
+ return content;
+ }
+
+ public abstract List<Element> apply(Element call);
+
+}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/TemplateFactory.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/TemplateFactory.java
new file mode 100644
index 0000000..23d1999
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/TemplateFactory.java
@@ -0,0 +1,29 @@
+package org.eclipse.epsilon.flexmi.templates;
+
+import org.eclipse.epsilon.flexmi.xml.Xml;
+import org.w3c.dom.Element;
+
+public class TemplateFactory {
+
+ protected static TemplateFactory instance;
+
+ public static TemplateFactory getInstance() {
+ if (instance == null) {
+ instance = new TemplateFactory();
+ }
+ return instance;
+ }
+
+ public TemplateFactory() {
+
+ }
+
+ public Template createTemplate(Element element) {
+ if ("EGL".contentEquals(Xml.getChild(element, "content").getAttribute("language"))) {
+ return new EglTemplate(element);
+ }
+ return new XmlTemplate(element);
+ }
+
+
+}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/XmlTemplate.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/XmlTemplate.java
new file mode 100644
index 0000000..7fdc735
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/XmlTemplate.java
@@ -0,0 +1,63 @@
+package org.eclipse.epsilon.flexmi.templates;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.text.StrLookup;
+import org.apache.commons.lang3.text.StrSubstitutor;
+import org.eclipse.epsilon.flexmi.xml.Xml;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class XmlTemplate extends Template {
+
+ public XmlTemplate(Element element) {
+ super(element);
+ }
+
+ public List<Element> apply(Element call) {
+
+ List<Element> application = getApplication(call);
+
+ for (Element applicationElement : application) {
+ for (String attributeName : Xml.getAttributeNames(call)) {
+ if (!attributeName.startsWith(Template.PREFIX)) {
+ applicationElement.setAttribute(attributeName, call.getAttribute(attributeName));
+ }
+ }
+ replaceParameters(applicationElement, call);
+ }
+
+ return application;
+ }
+
+ public List<Element> getApplication(Element call) {
+ List<Element> application = new ArrayList<Element>();
+ for (Element contentChild : Xml.getChildren(content)) {
+ application.add((Element) contentChild.cloneNode(true));
+ }
+ return application;
+ }
+
+ protected void replaceParameters(Element element, Element call) {
+
+ StrSubstitutor substitutor = new StrSubstitutor(new StrLookup<String>() {
+ @Override
+ public String lookup(String name) {
+ return call.getAttribute("_" + name);
+ }
+ });
+
+ for (Node attribute : Xml.getAttributes(element)) {
+ if (attribute.getNodeValue().indexOf("$") > -1) {
+ attribute.setNodeValue(substitutor.replace(attribute.getNodeValue()));
+ }
+ }
+
+ for (Element child : Xml.getChildren(element)) {
+ replaceParameters(child, call);
+ }
+
+ }
+
+}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/xml/PseudoSAXParser.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/xml/PseudoSAXParser.java
index 0a800f3..0353504 100644
--- a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/xml/PseudoSAXParser.java
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/xml/PseudoSAXParser.java
@@ -24,7 +24,8 @@
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.epsilon.flexmi.FlexmiDiagnostic;
import org.eclipse.epsilon.flexmi.FlexmiResource;
-import org.eclipse.epsilon.flexmi.Template;
+import org.eclipse.epsilon.flexmi.templates.Template;
+import org.eclipse.epsilon.flexmi.templates.TemplateFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -60,13 +61,13 @@
if (isFlexmiRootNode(document.getDocumentElement())) {
for (Element templateElement : Xml.getChildren(document.getDocumentElement(), Template.NODE_NAME)) {
- resource.getTemplates().add(new Template(templateElement));
+ resource.getTemplates().add(TemplateFactory.getInstance().createTemplate(templateElement));
document.getDocumentElement().removeChild(templateElement);
}
}
else {
if (isTemplate(document.getDocumentElement())) {
- resource.getTemplates().add(new Template(document.getDocumentElement()));
+ resource.getTemplates().add(TemplateFactory.getInstance().createTemplate(document.getDocumentElement()));
document.removeChild(document.getDocumentElement());
return;
}
@@ -81,15 +82,16 @@
Template template = null;
if (node instanceof Element) {
- if (!isFlexmiRootNode((Element) node)) {
- if (node.getNodeName().startsWith(Template.PREFIX)) {
- String templateName = node.getNodeName().substring(Template.PREFIX.length());
+ Element element = (Element) node;
+ if (!isFlexmiRootNode(element)) {
+ if (element.getNodeName().startsWith(Template.PREFIX)) {
+ String templateName = element.getNodeName().substring(Template.PREFIX.length());
for (Resource resource : this.resource.getResourceSet().getResources()) {
if (resource instanceof FlexmiResource) {
template = ((FlexmiResource) resource).getTemplate(templateName);
if (template != null) {
// ((FlexmiResource) resource).startProcessingFragment(resource.getURI());
- for (Element applicationElement : template.apply(node)) {
+ for (Element applicationElement : template.apply(element)) {
visit(applicationElement, handler);
}
break;
@@ -98,12 +100,12 @@
}
}
if (template == null) {
- resource.getWarnings().add(new FlexmiDiagnostic("Unknown template " + templateName, uri, resource.getLineNumber(node)));
+ resource.getWarnings().add(new FlexmiDiagnostic("Unknown template " + templateName, uri, resource.getLineNumber(element)));
return;
}
}
else {
- handler.startElement((Element) node);
+ handler.startElement(element);
}
}
}
diff --git a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/TemplateTests.java b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/TemplateTests.java
index 7237968..206b1ef 100644
--- a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/TemplateTests.java
+++ b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/TemplateTests.java
@@ -71,4 +71,13 @@
assertEval("EPackage.all.first().eClassifiers.at(0).name", "C1", "templates/model-with-template.flexmi");
}
+ @Test
+ public void testModelWithEglTemplates() throws Exception {
+ assertEval("EPackage.all.first().eClassifiers.at(0).name", "C1", "templates/model-with-egl-templates.flexmi");
+ assertEval("EPackage.all.first().eClassifiers.size()", 10, "templates/model-with-egl-templates.flexmi");
+ assertEval("EPackage.all.second().eClassifiers.at(0).name", "C11", "templates/model-with-egl-templates.flexmi");
+ assertEval("EPackage.all.third().eClassifiers.size()", 5, "templates/model-with-egl-templates.flexmi");
+ }
+
+
}
diff --git a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/models/templates/model-with-egl-templates.flexmi b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/models/templates/model-with-egl-templates.flexmi
new file mode 100644
index 0000000..7634549
--- /dev/null
+++ b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/models/templates/model-with-egl-templates.flexmi
@@ -0,0 +1,44 @@
+<?nsuri http://www.eclipse.org/emf/2002/Ecore?>
+<_>
+ <package name="p1">
+ <_t1/>
+ </package>
+
+ <package name="p2">
+ <_t2/>
+ </package>
+
+ <package name="p3">
+ <_t3 _n="5" abstract="true"/>
+ </package>
+
+ <_template name="t1">
+ <content language="EGL">
+ <![CDATA[
+ [%for (i in 1.to(10)){%]
+ <class name="C[%=i%]"/>
+ [%}%]
+ ]]>
+ </content>
+ </_template>
+
+ <_template name="t2">
+ <content language="EGL">
+ <![CDATA[
+ <class name="C[%=11%]"/>
+ ]]>
+ </content>
+ </_template>
+
+ <_template name="t3">
+ <parameter name="n"/>
+ <content language="EGL">
+ <![CDATA[
+ [%for (i in 1.to(n.asInteger())){%]
+ <class name="C[%=i%]"/>
+ [%}%]
+ ]]>
+ </content>
+ </_template>
+
+</_>
\ No newline at end of file