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