Added example of visualising the execution of an EOL program with Graphstream
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/.classpath b/examples/org.eclipse.epsilon.examples.graphstream/.classpath
new file mode 100644
index 0000000..26c8452
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/.classpath
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" output="target/classes" path="src">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/.project b/examples/org.eclipse.epsilon.examples.graphstream/.project
new file mode 100644
index 0000000..db8dc81
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.epsilon.examples.graphstream</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/.settings/org.eclipse.jdt.core.prefs b/examples/org.eclipse.epsilon.examples.graphstream/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..052ee6e
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,10 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=11
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/.settings/org.eclipse.m2e.core.prefs b/examples/org.eclipse.epsilon.examples.graphstream/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/META-INF/MANIFEST.MF b/examples/org.eclipse.epsilon.examples.graphstream/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..39682c0
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/META-INF/MANIFEST.MF
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Vis
+Bundle-SymbolicName: org.eclipse.epsilon.examples.graphstream
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: org.eclipse.epsilon.vis
+Bundle-RequiredExecutionEnvironment: JavaSE-11
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/build.properties b/examples/org.eclipse.epsilon.examples.graphstream/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/pom.xml b/examples/org.eclipse.epsilon.examples.graphstream/pom.xml
new file mode 100644
index 0000000..5e6b8e6
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/pom.xml
@@ -0,0 +1,60 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.epsilon.vis</groupId>
+ <artifactId>org.eclipse.epsilon.vis</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <release>11</release>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.graphstream</groupId>
+ <artifactId>gs-core</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.graphstream</groupId>
+ <artifactId>gs-ui-swing</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.epsilon</groupId>
+ <artifactId>org.eclipse.epsilon.eol.engine</artifactId>
+ <scope>compile</scope>
+ <version>2.4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.epsilon</groupId>
+ <artifactId>org.eclipse.epsilon.emc.emf</artifactId>
+ <scope>compile</scope>
+ <version>2.4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.epsilon</groupId>
+ <artifactId>org.eclipse.epsilon.flexmi</artifactId>
+ <scope>compile</scope>
+ <version>2.4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.emfatic</groupId>
+ <artifactId>org.eclipse.emfatic.core</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.platform</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/PropertyAccessGraph.java b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/PropertyAccessGraph.java
new file mode 100644
index 0000000..5999035
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/PropertyAccessGraph.java
@@ -0,0 +1,150 @@
+package org.eclipse.epsilon.examples.graphstream;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.emfatic.core.EmfaticResourceFactory;
+import org.eclipse.epsilon.emc.emf.EmfModel;
+import org.eclipse.epsilon.eol.EolModule;
+import org.eclipse.epsilon.eol.execute.introspection.recording.IPropertyAccessRecorder;
+import org.eclipse.epsilon.eol.execute.introspection.recording.PropertyAccessExecutionListener;
+import org.eclipse.epsilon.eol.execute.introspection.recording.PropertyAccesses;
+import org.eclipse.epsilon.flexmi.FlexmiResourceFactory;
+import org.graphstream.graph.Graph;
+import org.graphstream.graph.Node;
+import org.graphstream.graph.implementations.MultiGraph;
+
+public class PropertyAccessGraph {
+
+ public static void main(String args[]) throws Exception {
+ System.setProperty("org.graphstream.ui", "swing");
+ new PropertyAccessGraph().run();
+
+ }
+
+ public void run() throws Exception {
+
+ // Make Emfatic and Flexmi known to EMF
+ Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("flexmi", new FlexmiResourceFactory());
+ Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("emf", new EmfaticResourceFactory());
+
+ // Set up the graph
+ Graph graph = new MultiGraph("Property Access Graph");
+ // Set its stylesheet and antialias properties
+ graph.setAttribute("ui.stylesheet", "url('" + PropertyAccessGraph.class.getResource("style.css").toURI().toString() + "')");
+ graph.setAttribute("ui.antialias", "true");
+ graph.display();
+
+ // Set up the EMF model
+ EmfModel model = new EmfModel();
+ model.setName("M");
+ model.setMetamodelUri(EcorePackage.eNS_URI);
+ model.setModelFileUri(URI.createURI(PropertyAccessGraph.class.getResource("oo.emf").toURI().toString()));
+ model.load();
+
+ // Create a node for each element in the model
+ // and keep trace links in the "nodes" map
+ Map<Object, Node> nodes = new HashMap<>();
+ for (Object o : model.allContents()) {
+ EObject e = (EObject) o;
+ Node node = graph.addNode(UUID.randomUUID().toString());
+ node.setAttribute("ui.class", e.eClass().getName());
+ sleep(20);
+ nodes.put(o, node);
+ }
+
+ // Create edges for every non-derived reference
+ // in the model - including an edge to each element's container
+ for (Object o : model.allContents()) {
+ EObject e = (EObject) o;
+ for (EReference r : e.eClass().getEAllReferences()) {
+ List<Object> values = new ArrayList<>();
+
+ if (!(e.eIsSet(r) || r.isDerived())) continue;
+
+ if (r.isMany()) {
+ values.addAll((Collection) e.eGet(r));
+ }
+ else {
+ if (e.eIsSet(r)) values.add(nodes.get(e.eGet(r)));
+ }
+
+ for (Object value : values) {
+ if (nodes.containsKey(value) && nodes.containsKey(o)) {
+ graph.addEdge(UUID.randomUUID().toString(), nodes.get(o), nodes.get(value));
+ sleep(20);
+ }
+ }
+ }
+
+ // The edge to the container
+ if (e.eContainer() instanceof EObject && !nodes.get(o).hasEdgeBetween(nodes.get(e.eContainer()))) {
+ graph.addEdge(UUID.randomUUID().toString(), nodes.get(o), nodes.get(e.eContainer()));
+ sleep(20);
+ }
+ }
+
+ // Create an EOL module that prints the names of all elements in the model
+ EolModule module = new EolModule();
+ module.parse(PropertyAccessGraph.class.getResource("ecore.eol").toURI());
+
+ // Attach a listener to get notified every time a property
+ // of a model element is accessed (e.g. e.name)
+ module.getContext().getExecutorFactory().addExecutionListener(new PropertyAccessExecutionListener(new IPropertyAccessRecorder() {
+
+ @Override
+ public void stopRecording() {}
+
+ @Override
+ public void startRecording() {}
+
+ @Override
+ public void record(Object modelElement, String propertyName) {
+
+ // When a property of the model element is accessed add a shadow to it
+ // of proportional size to the # of times it has been accessed
+ Node node = nodes.get(modelElement);
+ if (node != null) {
+ Integer accesses = node.getAttribute("accesses", Integer.class);
+ if (accesses == null) { accesses = 0; }
+ accesses++;
+ node.setAttribute("accesses", accesses);
+ int shadowSize = accesses * 5;
+
+ // Add the shadow
+ node.setAttribute("ui.style", " shadow-mode: gradient-radial; \n"
+ + " shadow-width: " + shadowSize + "px; \n"
+ + " shadow-color: white; \n"
+ + " shadow-offset: 0px;");
+
+ // Wait for a bit to give time to the user to observe what is happening*/
+ sleep(50);
+ }
+ }
+
+ @Override
+ public PropertyAccesses getPropertyAccesses() { return null; }
+ }));
+
+ // Make the model available to the EOL program
+ module.getContext().getModelRepository().addModel(model);
+
+ // Execute the program
+ module.execute();
+
+ }
+
+ public void sleep(int millis) {
+ long now = System.currentTimeMillis();
+ while (System.currentTimeMillis() - now < millis) System.out.print("");
+ }
+}
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/ecore.eol b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/ecore.eol
new file mode 100644
index 0000000..5dccd77
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/ecore.eol
@@ -0,0 +1,10 @@
+for (e in ENamedElement.all) {
+ e.name.println();
+}
+
+EClass.all.collect(c|c.name);
+
+for (a in EAttribute.all) {
+ a.name.println();
+ a.eContainer().name.println();
+}
\ No newline at end of file
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/oo.emf b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/oo.emf
new file mode 100644
index 0000000..68dc093
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/oo.emf
@@ -0,0 +1,48 @@
+package OO;
+
+class Model {
+ @diagram(direction="down")
+ val Classifier[*] contents;
+}
+
+abstract class NamedElement {
+ attr String name;
+}
+
+@diagram(inheritance.direction="down")
+abstract class ~Classifier extends NamedElement {
+}
+
+class ~Class extends ~Classifier {
+ ref ~Class#extendedBy ~extends;
+ ref ~Class[*]#~extends extendedBy;
+ val Feature[*]#owner features;
+ attr boolean isAbstract;
+}
+
+@diagram(inheritance.direction="right")
+class Datatype extends ~Classifier {
+}
+
+abstract class Feature extends NamedElement {
+ ref ~Class#features owner;
+ attr VisibilityEnum visibility;
+}
+
+abstract class StructuralFeature extends Feature {
+}
+
+class Reference extends StructuralFeature {
+ @diagram(direction="up")
+ ref ~Class type;
+}
+
+class Attribute extends StructuralFeature {
+ attr boolean isMany;
+ ref Datatype type;
+}
+
+enum VisibilityEnum {
+ public = 1;
+ private = 2;
+}
\ No newline at end of file
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/oo.flexmi b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/oo.flexmi
new file mode 100644
index 0000000..440472f
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/oo.flexmi
@@ -0,0 +1,19 @@
+<?nsuri OO?>
+<model name="acme">
+ <!--
+ An object oriented model with two
+ classes and a reference between them
+ -->
+ <class name="Customer">
+ <attr name="fullname" type="String"/>
+ <attr name="active" type="Boolean"/>
+ </class>
+ <class name="Account">
+ <attr name="number" type="String"/>
+ <ref name="customer" type="Customer"/>
+ <attr name="balance" type="Real"/>
+ </class>
+ <type name="String"/>
+ <type name="Boolean"/>
+ <type name="Real"/>
+</model>
\ No newline at end of file
diff --git a/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/style.css b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/style.css
new file mode 100644
index 0000000..19cf018
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.graphstream/src/org/eclipse/epsilon/examples/graphstream/style.css
@@ -0,0 +1,46 @@
+graph {
+ fill-color: #1E1E1E;
+}
+
+edge {
+ shape: cubic-curve;
+ /*stroke-mode: plain;*/
+ size: 2px;
+ fill-color: #C0C0C0;
+ stroke-color: #C0C0C0;
+}
+
+node {
+ size: 20px, 20px;
+ shape: circle;
+ fill-color: #FB8500;
+}
+
+node.EClass {
+ fill-color: #8ECAE6;
+}
+
+node.EAttribute {
+ fill-color: #126782;
+}
+
+node.EReference {
+ fill-color: #FFB703;
+}
+
+node.EPackage {
+ fill-color: #FB8500;
+}
+
+node.EAnnotation {
+ fill-color: #FD9E02;
+}
+
+node.EEnum {
+ fill-color: #219EBC;
+}
+
+node.EEnumLiteral {
+ fill-color: #126782;
+}
+