From 9743e0f3e868ca04370ca8b56c201b6282b2628a Mon Sep 17 00:00:00 2001
From: Kevin Kassin <kevinkassin@gmx.de>
Date: Sat, 9 Sep 2017 20:29:03 +0200
Subject: [PATCH] Commit 9.9 20:30

added transformation package
---
 org.framed.orm.transformation/.classpath      |   7 ++
 org.framed.orm.transformation/.project        |  34 +++++
 .../.settings/org.eclipse.jdt.core.prefs      |   8 ++
 .../.settings/org.eclipse.m2e.core.prefs      |   4 +
 .../META-INF/MANIFEST.MF                      |  16 +++
 .../build.properties                          |   5 +
 .../epsilon/AllFeatures.eol                   |  41 ++++++
 .../epsilon/CardinalityParser.eol             |  22 ++++
 .../epsilon/CompartmentType.etl               |  96 ++++++++++++++
 .../epsilon/DataType.etl                      |  39 ++++++
 .../epsilon/Fulfillment.etl                   |  29 +++++
 .../epsilon/Group.etl                         |  18 +++
 .../epsilon/Inheritance.etl                   |  80 ++++++++++++
 .../epsilon/NaturalType.etl                   |  39 ++++++
 .../epsilon/ORM2CROM.etl                      |  63 ++++++++++
 .../epsilon/Relationship.etl                  | 119 ++++++++++++++++++
 .../epsilon/RelationshipExclusion.etl         |  11 ++
 .../epsilon/RelationshipImplication.etl       |  12 ++
 .../epsilon/RoleConstraints.etl               |  38 ++++++
 .../epsilon/RoleGroup.etl                     |  50 ++++++++
 .../epsilon/RoleType.etl                      |  41 ++++++
 .../epsilon/Type.etl                          | 111 ++++++++++++++++
 org.framed.orm.transformation/pom.xml         |  28 +++++
 .../framed/orm/transformation/Activator.java  |  51 ++++++++
 .../orm/transformation/EpsilonStandalone.java |  71 +++++++++++
 .../TransformationExecutor.java               |  85 +++++++++++++
 .../target/.gitignore                         |   1 +
 27 files changed, 1119 insertions(+)
 create mode 100644 org.framed.orm.transformation/.classpath
 create mode 100644 org.framed.orm.transformation/.project
 create mode 100644 org.framed.orm.transformation/.settings/org.eclipse.jdt.core.prefs
 create mode 100644 org.framed.orm.transformation/.settings/org.eclipse.m2e.core.prefs
 create mode 100644 org.framed.orm.transformation/META-INF/MANIFEST.MF
 create mode 100644 org.framed.orm.transformation/build.properties
 create mode 100644 org.framed.orm.transformation/epsilon/AllFeatures.eol
 create mode 100644 org.framed.orm.transformation/epsilon/CardinalityParser.eol
 create mode 100644 org.framed.orm.transformation/epsilon/CompartmentType.etl
 create mode 100644 org.framed.orm.transformation/epsilon/DataType.etl
 create mode 100644 org.framed.orm.transformation/epsilon/Fulfillment.etl
 create mode 100644 org.framed.orm.transformation/epsilon/Group.etl
 create mode 100644 org.framed.orm.transformation/epsilon/Inheritance.etl
 create mode 100644 org.framed.orm.transformation/epsilon/NaturalType.etl
 create mode 100644 org.framed.orm.transformation/epsilon/ORM2CROM.etl
 create mode 100644 org.framed.orm.transformation/epsilon/Relationship.etl
 create mode 100644 org.framed.orm.transformation/epsilon/RelationshipExclusion.etl
 create mode 100644 org.framed.orm.transformation/epsilon/RelationshipImplication.etl
 create mode 100644 org.framed.orm.transformation/epsilon/RoleConstraints.etl
 create mode 100644 org.framed.orm.transformation/epsilon/RoleGroup.etl
 create mode 100644 org.framed.orm.transformation/epsilon/RoleType.etl
 create mode 100644 org.framed.orm.transformation/epsilon/Type.etl
 create mode 100644 org.framed.orm.transformation/pom.xml
 create mode 100644 org.framed.orm.transformation/src/org/framed/orm/transformation/Activator.java
 create mode 100644 org.framed.orm.transformation/src/org/framed/orm/transformation/EpsilonStandalone.java
 create mode 100644 org.framed.orm.transformation/src/org/framed/orm/transformation/TransformationExecutor.java
 create mode 100644 org.framed.orm.transformation/target/.gitignore

diff --git a/org.framed.orm.transformation/.classpath b/org.framed.orm.transformation/.classpath
new file mode 100644
index 00000000..46cec6ed
--- /dev/null
+++ b/org.framed.orm.transformation/.classpath
@@ -0,0 +1,7 @@
+<?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-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src/"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.framed.orm.transformation/.project b/org.framed.orm.transformation/.project
new file mode 100644
index 00000000..bb45fec9
--- /dev/null
+++ b/org.framed.orm.transformation/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.framed.orm.transformation</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/org.framed.orm.transformation/.settings/org.eclipse.jdt.core.prefs b/org.framed.orm.transformation/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..443e0859
--- /dev/null
+++ b/org.framed.orm.transformation/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/org.framed.orm.transformation/.settings/org.eclipse.m2e.core.prefs b/org.framed.orm.transformation/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 00000000..f897a7f1
--- /dev/null
+++ b/org.framed.orm.transformation/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.framed.orm.transformation/META-INF/MANIFEST.MF b/org.framed.orm.transformation/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..e1cdeb54
--- /dev/null
+++ b/org.framed.orm.transformation/META-INF/MANIFEST.MF
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Transformation
+Bundle-SymbolicName: org.framed.orm.transformation;singleton:=true
+Bundle-Version: 2.0.3
+Bundle-Activator: org.framed.orm.transformation.Activator
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.epsilon.eol.engine,
+ org.eclipse.epsilon.emc.emf,
+ org.eclipse.epsilon.eol.dt;bundle-version="1.2.0",
+ org.eclipse.epsilon.etl.engine,
+ org.rosi.crom.metamodel;bundle-version="0.1.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Export-Package: org.framed.orm.transformation
diff --git a/org.framed.orm.transformation/build.properties b/org.framed.orm.transformation/build.properties
new file mode 100644
index 00000000..118b0c02
--- /dev/null
+++ b/org.framed.orm.transformation/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = target/classes/
+bin.includes = META-INF/,\
+			   .,\
+			   epsilon/
diff --git a/org.framed.orm.transformation/epsilon/AllFeatures.eol b/org.framed.orm.transformation/epsilon/AllFeatures.eol
new file mode 100644
index 00000000..568a1382
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/AllFeatures.eol
@@ -0,0 +1,41 @@
+//Set of all available features
+operation getAllFeatures() : Set { 
+	var set : Set;
+	set.add("Role_Types");
+	set.add("Role_Structure");
+	set.add("Role_Properties");
+	set.add("Role_Behavior");
+	set.add("Role_Inheritance");
+	set.add("Playable");
+	set.add("Players");
+	set.add("Naturals");
+	set.add("Compartments");
+	set.add("Dates");
+	set.add("Roles");
+	set.add("Dependent");
+	set.add("On_Compartments");
+	set.add("On_Relationships");
+	set.add("Role_Constraints");
+	set.add("Role_Implication");
+	set.add("Role_Prohibition");
+	set.add("Role_Equivalence");
+	set.add("Group_Constraints");
+	set.add("Occurrence_Constraints");
+	set.add("Relationships");
+	set.add("Relationship_Constraints");
+	set.add("Relationship_Cardinality");
+	set.add("Intra_Relationship_Constraints");
+	set.add("Parthood_Constraints");
+	set.add("Inter_Relationship_Constraints");
+	set.add("Contains_Compartments");
+	set.add("Compartment_Types");
+	set.add("Compartment_Structure");
+	set.add("Compartment_Properties");
+	set.add("Compartment_Behavior");
+	set.add("Compartment_Inheritance");
+	set.add("Participants");
+	set.add("Playable_by_Defining_Compartment");
+	set.add("Data_Types");
+	set.add("Data_Type_Inheritance");
+	return set;
+}
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/CardinalityParser.eol b/org.framed.orm.transformation/epsilon/CardinalityParser.eol
new file mode 100644
index 00000000..e4a41ff3
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/CardinalityParser.eol
@@ -0,0 +1,22 @@
+operation parseCardinality(card : String) : Sequence(Integer) { 
+		var result = new Sequence(Integer);
+		
+		if(card.matches(".*\\(.*\\).*")) {
+			card = card.substring(card.indexOf("(") + 1, card.indexOf(")"));
+		}
+		
+		if (card.matches("[0-9]+\\.\\.[0-9]+")) {
+			var cards = card.split("\\.\\.");
+			result.add(new Native("java.lang.Integer")(cards[0]));
+			result.add(new Native("java.lang.Integer")(cards[1]));
+		} else if (card.matches("[0-9]+\\.\\.\\*")) {
+			var cards = card.split("\\.\\.");
+			result.add(new Native("java.lang.Integer")(cards[0]));
+		} else if (card.matches("[0-9]+")) {
+			var x = new Native("java.lang.Integer")(card);
+			result.add(x);
+			result.add(x);
+		}
+
+		return result;
+}
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/CompartmentType.etl b/org.framed.orm.transformation/epsilon/CompartmentType.etl
new file mode 100644
index 00000000..0b60f6eb
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/CompartmentType.etl
@@ -0,0 +1,96 @@
+import "Type.etl";
+import "CardinalityParser.eol";
+
+pre CompartmentType {
+	var compartmentTypes : OrderedSet(source!Shape);
+}
+
+/**
+ * Transforms a shape with type COMPARTMENT_TYPE.
+ */
+@lazy 
+rule CompartmentType
+	transform t : source!Shape
+	to n : target!CompartmentType {
+
+	guard : t.getType.getValue == 0 // enum value COMPARTMENT_TYPE
+
+	compartmentTypes.add(t);
+
+	var children = t.getModel();
+	if (not (children == null)) {
+		for(e in children.elements) e.~features=t.~features;
+	
+		// iterate over all children of the compartment type	
+		for (elem : source!ModelElement in children.elements) {
+			
+			var e = elem.equivalent();
+			
+			if (e == null) { continue; }
+			if (e.instanceOf(target!AbstractRole)) { 			// ROLE
+				// create a new part with the role
+				var part = new target!Part;
+				part.role = e;
+				part.whole = n;
+				// parse the lower and upper bound from the role
+				var desc = elem.description;
+				if (not (desc == null) and t.~features.get("Occurrence_Constraints")) {
+					var card = desc.name;
+					var cards = parseCardinality(card);
+					
+					if(cards.size()>0) {
+						part.lower = cards[0];
+						if(cards.size()>1) {
+							part.upper = cards[1];
+						}				
+					}	
+				}				
+				// add the new part to the compartment
+				n.getParts().add(part);
+			} else if (e.instanceOf(target!CompartmentType)) {	//COMPARTMENT_TYPE
+				n.getContains.add(e);
+				if(not(t.~features.get("Contains_Compartments"))) n.getContains.remove(e);
+			} else if (e.instanceOf(target!RelationshipImplication) or e.instanceOf(target!RelationshipExclusion)) { // INTER_RELATIONSHIP_CONSTRAINT
+				for (rst : source!Relation in children.elements){
+					if (rst.getType.getValue == 7){ // RELATIONSHIP
+						//Discover source and target Relationships of the inter relationship constraint
+						if (rst.connectionAnchor == elem.source)
+							e.first = rst.equivalent();
+						if (rst.connectionAnchor == elem.target)
+							e.second = rst.equivalent();
+					}						
+				}
+				n.getConstraints().add(e);	//add CONSTRAINTS as well			
+			} else if ( e.instanceOf(target!Constraint)) {		// CONSTRAINT
+				n.getConstraints().add(e);
+			} else if ( e.instanceOf(target!Relationship)) {	// RELATIONSHIP
+				n.getRelationships().add(e);
+			} else if ( e.instanceOf(target!RoleInheritance)) {
+				t.~parent.relations.add(e);
+			} 		
+		}
+	}
+	
+	n.name = t.name;
+}
+
+/**
+ * Add operations and attributes in the post processing step.
+ *
+ * This separation is necessary as the type references in attributes and operations may form cycles between
+ * types/shapes. The post block ensures that these cycles can be resolved.
+ */
+post CompartmentType {
+	for (t : source!Shape in compartmentTypes) {
+		var n = t.equivalent();
+
+		if (not n.isDefined() or not t.isDefined()) {
+			continue;
+		}
+
+		if(t.~features.get("Compartment_Behavior")) { //feature Compartment_Behavior implies feature Compartment_Properties (not to check)
+			t.addAttributes(n);
+		    t.addOperations(n);
+		}	
+	}
+}
diff --git a/org.framed.orm.transformation/epsilon/DataType.etl b/org.framed.orm.transformation/epsilon/DataType.etl
new file mode 100644
index 00000000..1ffb5de4
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/DataType.etl
@@ -0,0 +1,39 @@
+import "Type.etl";
+
+pre DataType {
+	var dataTypes : OrderedSet(source!Shape);
+}
+
+/**
+ * Transforms a shape with type DATA_TYPE.
+ */
+@lazy 
+rule DataType
+	transform t : source!Shape
+	to n : target!DataType {
+
+	guard : t.getType.getValue == 3 and t.~features.get("Data_Types") // enum value DATA_TYPE
+
+	n.name = t.name;
+
+	dataTypes.add(t);
+}
+
+/**
+ * Add operations and attributes in the post processing step.
+ *
+ * This separation is necessary as the type references in attributes and operations may form cycles between
+ * types/shapes. The post block ensures that these cycles can be resolved.
+ */
+post DataType {
+	for (t : source!Shape in dataTypes) {
+		var n = t.equivalent();
+
+		if (not n.isDefined() or not t.isDefined()) {
+			continue;
+		}
+
+		t.addAttributes(n);
+		t.addOperations(n);
+	}
+}
diff --git a/org.framed.orm.transformation/epsilon/Fulfillment.etl b/org.framed.orm.transformation/epsilon/Fulfillment.etl
new file mode 100644
index 00000000..5fca6925
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/Fulfillment.etl
@@ -0,0 +1,29 @@
+operation toTransform(t : source!Relation) : Boolean {
+	//check source of fulfillment and fitting feature
+	switch(t.source.getType.getValue) {
+		case 0: if(t.~features.get("Compartments")) {
+					if(not(t.source==t.target)) return true;
+					if((t.source==t.target and t.~features.get("Playable_by_Defining_Compartment"))) return true;
+				}
+		case 1: return true;
+		//case 2: if(t.~features.get("Roles")) return true;
+		case 3: if(t.~features.get("Dates")) return true;
+	}
+	return false;
+}
+
+@lazy 
+rule Fulfillment
+	transform t : source!Relation
+	to n : Sequence(target!Fulfillment) {
+	
+	guard : t.getType.getValue == 14 // enum value Fulfillment
+	if(toTransform(t)){
+		for(role : source!Shape in t.referencedRoles) {
+			var fulfillment = new target!Fulfillment;
+			fulfillment.filler ::= t.source;
+			fulfillment.filled ::= role;
+			n.add(fulfillment);
+		}	
+	}
+}
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/Group.etl b/org.framed.orm.transformation/epsilon/Group.etl
new file mode 100644
index 00000000..a2b0438a
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/Group.etl
@@ -0,0 +1,18 @@
+@lazy 
+rule Group
+	transform s : source!Shape
+	to t : target!Group {	
+	guard : s.getType.value == 13	// GROUP
+	
+	t.name = s.name;	
+	
+	var children = s.`model`;
+	if (not (children == null)) {
+		for(e in children.elements) e.~features=s.~features;
+		for (elem : source!ModelElement in children.elements) {
+			var e = elem.equivalent();
+			if(not(e==null))t.getElements().add(e);
+		}
+	}
+	
+}
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/Inheritance.etl b/org.framed.orm.transformation/epsilon/Inheritance.etl
new file mode 100644
index 00000000..a8e1ddb3
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/Inheritance.etl
@@ -0,0 +1,80 @@
+/**
+ * Sets the source and target attributes of the inheritance relation and adds the relation to 
+ * the incoming and outgoing relations of its source and target. 
+ *
+ * It is assumed that source and target reference are valid, i.e., are of the same type and correspond
+ * to the inheritance. For instance, a NaturalInheritance has source and target elements of type NaturalType.
+ */
+operation Any transformInheritance(s : source!Relation, t : target!Inheritance) {
+	var relationSource = s.getSource.equivalent();
+	var relationTarget = s.getTarget.equivalent();
+	
+	t.sub = relationSource;
+	t.super = relationTarget;
+	
+	relationSource.getOutgoing.add(t);
+	relationTarget.getIncoming.add(t);	
+}
+
+/**
+ * Transforms a relation with type INHERITANCE between two elements of type COMPARTMENT_TYPE.
+ */
+@lazy 
+rule CompartmentInheritance
+	transform s : source!Relation
+	to t : target!CompartmentInheritance {
+
+	guard : s.getType.getValue == 6 //enum value INHERITANCE 
+		and s.getSource.getType.getValue == 0 // COMPARTMENT_TYPE
+		and s.getTarget.getType.getValue == 0 // COMPARTMENT_TYPE
+		and s.~features.get("Compartment_Inheritance") // FEATURES
+		
+	transformInheritance(s, t);
+}
+
+/**
+ * Transforms a relation with type INHERITANCE between two elements of type NATURAL_TYPE.
+ */
+@lazy 
+rule NaturalInheritance
+	transform s : source!Relation
+	to t : target!NaturalInheritance {
+
+	guard : s.getType.getValue == 6 // enum value INHERITANCE
+		and s.getSource.getType.getValue == 1 // NATURAL_TYPE
+		and s.getTarget.getType.getValue == 1 // NATURAL_TYPE
+
+	transformInheritance(s, t);
+}
+
+/**
+ * Transforms a relation with type INHERITANCE between two elements of type ROLE_TYPE.
+ */
+@lazy  
+rule RoleInheritance
+	transform s : source!Relation
+	to t : target!RoleInheritance {
+
+	guard : s.getType.getValue == 6 // enum value INHERITANCE
+		and s.getSource.getType.getValue == 2 // ROLE_TYPE
+		and s.getTarget.getType.getValue == 2 // ROLE_TYPE
+		and s.~features.get("Role_Inheritance") // FEATURES
+	
+	transformInheritance(s, t);
+}
+
+/**
+ * Transforms a relation with type INHERITANCE between two elements of type DATA_TYPE.
+ */
+@lazy  
+rule DataInheritance
+	transform s : source!Relation
+	to t : target!DataInheritance {
+
+	guard : s.getType.getValue == 6 // enum value INHERITANCE
+		and s.getSource.getType.getValue == 3 // DATA_TYPE
+		and s.getTarget.getType.getValue == 3 // DATA_TYPE
+		and s.~features.get("Data_Type_Inheritance") //FEATURES
+	
+	transformInheritance(s, t);
+}
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/NaturalType.etl b/org.framed.orm.transformation/epsilon/NaturalType.etl
new file mode 100644
index 00000000..82eb63b4
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/NaturalType.etl
@@ -0,0 +1,39 @@
+import "Type.etl";
+
+pre NaturalType {
+	var naturalTypes : OrderedSet(source!Shape);
+}
+
+/**
+ * Transforms a shape with type NATURAL_TYPE.
+ */
+ @lazy 
+rule NaturalType
+	transform t : source!Shape
+	to n : target!NaturalType {
+
+	guard : t.getType.getValue == 1
+	
+	n.name = t.name;
+	
+	naturalTypes.add(t);	
+}
+
+/**
+ * Add operations and attributes in the post processing step. 
+ *
+ * This separation is necessary as the type references in attributes and operations may form cycles between 
+ * types/shapes. The post block ensures that these cycles can be resolved.
+ */
+post NaturalType {
+	for (t : source!Shape in naturalTypes) {		
+		var n = t.equivalent();
+		
+		if (not n.isDefined() or not t.isDefined()) {
+			continue;
+		}
+		
+		t.addAttributes(n);
+		t.addOperations(n);		
+	}
+}
diff --git a/org.framed.orm.transformation/epsilon/ORM2CROM.etl b/org.framed.orm.transformation/epsilon/ORM2CROM.etl
new file mode 100644
index 00000000..b1b774a5
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/ORM2CROM.etl
@@ -0,0 +1,63 @@
+import "CompartmentType.etl";
+import "DataType.etl";
+import "NaturalType.etl";
+import "RoleType.etl";
+
+import "RoleGroup.etl";
+import "Group.etl";
+
+import "RoleConstraints.etl";
+import "RelationshipImplication.etl";
+import "RelationshipExclusion.etl";
+
+import "Inheritance.etl";
+import "Relationship.etl";
+import "Fulfillment.etl";
+
+import "AllFeatures.eol";
+
+operation Any println() : Any { 
+	("Printing : " + self)->println();
+}
+
+operation Any setFeatureMap() : Map {
+	for(s : String in getAllFeatures()) self.put(s, false);
+}
+
+rule ORM2CROM
+	transform mym : source!Model
+	to crom : target!Model {
+	guard : mym.parent == null
+	
+	var featureMap : Map;
+	featureMap.setFeatureMap();
+	for(f in mym.framedConfiguration.features) {
+		featureMap.put(f.getName().asString(), true);
+	}
+	for(e in mym.elements) { 
+		e.~features=featureMap;
+		e.~parent=crom;
+	}
+	
+	for(shape : source!Shape in mym.elements) {
+		var x = shape.equivalent();
+		if(not ((x == null) or x.instanceOf(target!AbstractRole))) {
+			crom.elements.add(x);
+		}
+	}
+	
+	for (relation : source!Relation in mym.elements) {
+		var r = relation.equivalent();
+		if (not (r == null)) {
+			if(not(r.isKindOf(Sequence))) {
+				crom.relations.add(r);
+			} else {
+				for(ob in r) {
+					crom.relations.add(ob);
+				}
+			}
+		}
+	}
+	
+}
+
diff --git a/org.framed.orm.transformation/epsilon/Relationship.etl b/org.framed.orm.transformation/epsilon/Relationship.etl
new file mode 100644
index 00000000..8c001616
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/Relationship.etl
@@ -0,0 +1,119 @@
+/**
+ * Transforms a relation with type INHERITANCE.
+ */
+
+operation getPlace(card : String,holder:target!RoleType) : target!Place {
+	var place = new target!Place;
+	place.lower = 0;
+	place.upper = -1;
+	if(card.isDefined()) {
+		var cards = parseCardinality(card);
+		if(cards.size()==1)
+			place.lower = cards[0];
+		if(cards.size()>1){
+			place.lower = cards[0];
+			place.upper = cards[1];
+		}				
+	}
+	if(holder.isDefined()){
+		place.holder = holder;
+	}
+	return place;
+}
+
+operation getPlace(card : String,holder:target!RigidType) : target!Place {
+	fail("Place can only reference role types as placeholders!");
+}
+
+@lazy 
+rule Relationship
+	transform s : source!Relation
+	to t : target!Relationship {
+
+	guard : s.getType.getValue == 7 and s.~features.get("Relationships") // enum value RELATIONSHIP
+	
+	t.name = s.name;
+	
+	if(s.~features.get("Relationship_Cardinality")) { // feature Relationship_Cardinality implies feature Relationship_Constraints (not to check)	
+		//Place should always be defined
+		var card = "0..*";
+		if(s.sourceLabel.isDefined()){
+			card=s.sourceLabel.name;
+		}
+		var place = getPlace(card,s.getSource.equivalent());
+		if(not(place==null)) {
+			t.setFirst(place);
+		}
+		
+		//Place should always be defined
+		card="0..*";
+		if(s.targetLabel.isDefined()){
+			card=s.targetLabel.name;
+		}
+		place = getPlace(card,s.getTarget.equivalent());
+		if(not(place==null)) {
+			t.setSecond(place);
+		}
+	} else {
+		var place = getPlace("0...*",s.getSource.equivalent());
+		t.setFirst(place);
+		place = getPlace("0...*",s.getTarget.equivalent());
+		t.setSecond(place);
+	}		
+		
+		//t.first - place from label
+		//t.second - place from label
+		
+		s.getSource.equivalent().getOutgoing.add(t);
+		s.getTarget.equivalent().getIncoming.add(t);
+	
+		for (r : source!Relation in s.referencedRelation) {
+			var referenced = r.equivalent();
+			if(not(referenced == null))referenced.setRelation(t);
+		}
+}
+
+@lazy 
+rule TotalRelation
+	transform s : source!Relation
+	to t : target!Total {
+	
+	guard : s.getType.getValue == 8 and s.~features.get("Intra_Relationship_Constraints")
+	
+}
+
+@lazy 
+rule CyclicRelation
+	transform s : source!Relation
+	to t : target!Cyclic {
+	
+	guard : s.getType.getValue == 9 and s.~features.get("Intra_Relationship_Constraints") 
+	
+}  
+
+@lazy 
+rule IrreflexiveRelation
+	transform s : source!Relation
+	to t : target!Irreflexive {
+	
+	guard : s.getType.getValue == 10 and s.~features.get("Intra_Relationship_Constraints") 
+	
+} 
+
+@lazy 
+rule AcyclicRelation
+	transform s : source!Relation
+	to t : target!Acyclic {
+	
+	guard : s.getType.getValue == 17 and s.~features.get("Intra_Relationship_Constraints") 
+	
+} 
+
+@lazy 
+rule ReflexiveRelation
+	transform s : source!Relation 
+	to t : target!Reflexive {
+	
+	guard : s.getType.getValue == 18 and s.~features.get("Intra_Relationship_Constraints") 
+	
+} 
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/RelationshipExclusion.etl b/org.framed.orm.transformation/epsilon/RelationshipExclusion.etl
new file mode 100644
index 00000000..17769b91
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/RelationshipExclusion.etl
@@ -0,0 +1,11 @@
+@lazy 
+rule RelationshipExclusion
+	transform s : source!Relation
+	to t : target!RelationshipExclusion {
+
+	guard : s.getType.getValue == 19 and s.~features.get("Inter_Relationship_Constraints") // enum value RelationshipExclusion
+	
+	//does not work as RelationshipShapeChild has no ref to the actual Relationship
+	//t.first ::= s.source;
+	//t.second ::= s.target;
+}
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/RelationshipImplication.etl b/org.framed.orm.transformation/epsilon/RelationshipImplication.etl
new file mode 100644
index 00000000..cbbf10a7
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/RelationshipImplication.etl
@@ -0,0 +1,12 @@
+@lazy 
+rule RelationshipImplication
+	transform s : source!Relation
+	to t : target!RelationshipImplication {
+
+	guard : s.getType.getValue == 15 and s.~features.get("Inter_Relationship_Constraints") // enum value RelationshipImplication
+		
+
+	//does not work as RelationshipShapeChild has no ref to the actual Relationship
+	//t.first = s.source.equivalent();
+	//t.second = s.target.equivalent();
+}
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/RoleConstraints.etl b/org.framed.orm.transformation/epsilon/RoleConstraints.etl
new file mode 100644
index 00000000..ae388331
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/RoleConstraints.etl
@@ -0,0 +1,38 @@
+@abstract
+@lazy 
+rule RoleConstraint
+	transform t : source!Relation
+	to n : target!RoleConstraint {	
+	n.first ::= t.source;
+	n.second ::= t.target;	
+}
+
+// RoleImplication
+@lazy 
+rule RoleImplication
+	transform t : source!Relation
+	to n : target!RoleImplication 
+	extends RoleConstraint {
+	guard : t.getType.getValue == 4 // enum value RoleImplication
+		and t.~features.get("Role_Implication") //feature
+}
+
+// RoleProhibition
+@lazy 
+rule RoleProhibition
+	transform t : source!Relation
+	to n : target!RoleProhibition 
+	extends RoleConstraint {
+	guard : t.getType.getValue == 11 // enum value RoleImplication
+		and t.~features.get("Role_Prohibition") //feature
+}
+
+// RoleEquivalence
+@lazy 
+rule RoleEquivalence
+	transform t : source!Relation
+	to n : target!RoleEquivalence 
+	extends RoleConstraint {
+	guard : t.getType.getValue == 5 // enum value RoleEquivalence
+		and t.~features.get("Role_Equivalence") //feature
+}
\ No newline at end of file
diff --git a/org.framed.orm.transformation/epsilon/RoleGroup.etl b/org.framed.orm.transformation/epsilon/RoleGroup.etl
new file mode 100644
index 00000000..c042fe19
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/RoleGroup.etl
@@ -0,0 +1,50 @@
+import "CardinalityParser.eol";
+
+@lazy 
+rule RoleGroup
+	transform s : source!Shape
+	to t : target!RoleGroup {	
+	guard : s.getType.value == 12	// ROLEGROUP
+		
+	t.name = s.name;
+	if(s.name.indexOf("(")>-1) {
+		t.name = s.name.substring(0,s.name.indexOf("(")).trim();
+	}
+	
+	var desc = s.name;
+	if (not (desc == null) and s.~features.get("Group_Constraints")) { //feature Group_Constraints implies feature Role_Constraints (not to check)
+		var cards = parseCardinality(desc);
+		if(cards.size()>0) {
+			t.lower = cards[0];
+		}
+		if(cards.size()>1) {
+			t.upper = cards[1];
+		}
+	} 
+	
+	var children = s.`model`;
+	if (not (children == null)) {
+		for(c in children.elements) c.~features=s.~features;
+		for (elem : source!ModelElement in children.elements) {
+			var e = elem.equivalent();
+			
+			if (e.instanceOf(target!RoleGroupElement)) {
+				t.getElements().add(e);				
+			} else if(e.instanceOf(target!Relation)) {
+				var compTypeFound = false;
+				var compType = s;
+				while(not(compTypeFound)) {
+					compType = compType.eContainer();
+					compTypeFound = not(compType.instanceOf(source!Model)) and compType.getType.getValue == 0;
+				}
+				if(e.instanceOf(target!Constraint)) {
+					compType.equivalent().getConstraints().add(e);
+				} else {
+					compType.equivalent().getRelationships().add(e);
+				}
+			} else {
+				// TODO: print warning or throw exception
+			}			
+		}
+	}	
+}
diff --git a/org.framed.orm.transformation/epsilon/RoleType.etl b/org.framed.orm.transformation/epsilon/RoleType.etl
new file mode 100644
index 00000000..7c8662b4
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/RoleType.etl
@@ -0,0 +1,41 @@
+import "Type.etl";
+
+pre RoleType {
+	var roleTypes : OrderedSet(source!Shape);
+}
+
+/**
+ * Transforms a shape with type ROLE_TYPE.
+ */
+ @lazy 
+rule RoleType
+	transform t : source!Shape
+	to n : target!RoleType {
+
+	guard : t.getType.getValue == 2 // enum value ROLE_TYPE
+
+	n.name = t.name;
+	
+	roleTypes.add(t);
+}
+
+/**
+ * Add operations and attributes in the post processing step.
+ *
+ * This separation is necessary as the type references in attributes and operations may form cycles between
+ * types/shapes. The post block ensures that these cycles can be resolved.
+ */
+post RoleType {
+	for (t : source!Shape in roleTypes) {
+		var n = t.equivalent();
+
+		if (not n.isDefined() or not t.isDefined()) {
+			continue;
+		}
+
+		if(t.~features.get("Role_Behavior")) { //feature Role_Behavior implies feature Role_Properties and Role_Structure (not to check)
+			t.addAttributes(n);
+			t.addOperations(n);
+		}	
+	}
+}
diff --git a/org.framed.orm.transformation/epsilon/Type.etl b/org.framed.orm.transformation/epsilon/Type.etl
new file mode 100644
index 00000000..2c1c6012
--- /dev/null
+++ b/org.framed.orm.transformation/epsilon/Type.etl
@@ -0,0 +1,111 @@
+/**
+ * Parses the elements in the shape's first segment to attributes and adds them to the target element.
+ * 
+ * When parsing attribute strings, a valid format is assumed by the transformation!  
+ * A valid format conforms to the following schema for each attribute: '<name> : <type>'.
+ * 
+ * The name has to be a valid identifier, i.e. it starts with a letter and only contains letters and numbers.
+ * The type has to be another model element.  
+ */
+operation source!Shape addAttributes(n : target!Type) {	
+	var attributes = self.firstSegment;
+		
+	if(not (attributes == null) ) {
+		for(ele : source!NamedElement in attributes.elements) {
+			var attribute = new target!Attribute;
+			attribute.owner = n;
+			
+			var attString = ele.name.replaceAll(" +", "");
+			var tokens = attString.split(":");
+			var attName = tokens[0];
+			var attType = findTypeForName(tokens[1]);
+						
+			attribute.name = attName;
+			if (not (attType == null)) {
+				attribute.type = attType;
+			}
+			
+			n.attributes.add(attribute);
+		}
+	}
+}
+
+/**
+ * Parses the elements in the shape's second segment to operations and adds them to the target element.
+ * 
+ * When parsing operation strings, a valid format is assumed by the transformation!
+ * 
+ * A valid format conforms to the following schema: '<name> ( <parameters> ) : <type>'.
+ * Whitespace characters can occur in between. The name has to be a valid identifier, i.e. it starts with 
+ * a letter and only contains letters and numbers.
+ * The type has to be another model element. The parameters are a (probably empty) comma-separated list of 
+ * '<parameterName> : <parameterType>' pairs, where the name and type follow the same constraints as above. 
+ */
+operation source!Shape addOperations(n : target!Type) {
+	var operations = self.secondSegment;
+	
+	if (operations == null) {
+		return;
+	}
+	
+	for (ele : source!NamedElement in operations.elements) {
+		var tokens = ele.name.split("[\\(\\)]");
+		var opName = tokens[0].replaceAll(" +", "");
+		
+		// parse parameters if possible
+		var pars = null;
+		if(tokens.size()>1) {
+			pars = tokens[1];
+		}
+		
+		// parse return type if possible
+		var opType = null;
+		if(tokens.size()>2) {
+			opType = tokens[2].replaceAll("[ \\:]", "");
+		}
+		
+		var op = new target!Operation;
+		op.owner = n;
+		op.name = opName;
+							
+		if(not (opType == null)) {
+			var t = findTypeForName(opType);
+			if (not (t == null)) {
+				op.type = t;
+			}
+		}
+		
+		if (not (pars == null or pars.isEmpty())) {
+			for (param : String in pars.split(",")) {
+				var paramSpec = param.split(":"); 
+				var paramName = paramSpec[0].replaceAll(" +", "");
+				var paramType = paramSpec[1].replaceAll(" +", "");
+				
+				var parameter = new target!Parameter;
+				parameter.name = paramName;
+				
+				var pt = findTypeForName(paramType);			
+				if (not (pt == null)) {
+					parameter.type = pt;
+				}
+				op.params.add(parameter);					 
+			}
+		}
+		
+		n.operations.add(op);
+	}
+}
+
+/**
+ * Returns the equivalent Type to the given name, if any.
+ * 
+ * Searches the source model for a shape element with the given name and returns the equivalent target model element 
+ * if a shape of given name was found, or null otherwise.
+ */
+operation Any findTypeForName(str : String) : target!Type {
+	var shape = source!Shape.allInstances().select(s|s.name = str).first;
+	if (shape.isDefined()) {
+		return shape.equivalent();
+	}
+	return null;
+} 
diff --git a/org.framed.orm.transformation/pom.xml b/org.framed.orm.transformation/pom.xml
new file mode 100644
index 00000000..1fadc11a
--- /dev/null
+++ b/org.framed.orm.transformation/pom.xml
@@ -0,0 +1,28 @@
+<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.framed.orm.transformation</groupId>
+  <artifactId>org.framed.orm.transformation</artifactId>
+  
+  <parent>
+    <relativePath>../org.framed.orm.build/pom.xml</relativePath>
+    <groupId>org.framed</groupId>
+    <artifactId>parent</artifactId>
+    <version>2.0.3</version>
+  </parent>
+  
+  <build>
+    <sourceDirectory>src</sourceDirectory>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  
+  <packaging>eclipse-plugin</packaging>
+</project>
\ No newline at end of file
diff --git a/org.framed.orm.transformation/src/org/framed/orm/transformation/Activator.java b/org.framed.orm.transformation/src/org/framed/orm/transformation/Activator.java
new file mode 100644
index 00000000..c070661f
--- /dev/null
+++ b/org.framed.orm.transformation/src/org/framed/orm/transformation/Activator.java
@@ -0,0 +1,51 @@
+package org.framed.orm.transformation;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+  // The plug-in ID
+  public static final String PLUGIN_ID = "org.framed.orm.transformation"; //$NON-NLS-1$
+
+  // The shared instance
+  private static Activator plugin;
+
+  /**
+   * The constructor
+   */
+  public Activator() {}
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+   */
+  public void start(BundleContext context) throws Exception {
+    super.start(context);
+    plugin = this;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+   */
+  public void stop(BundleContext context) throws Exception {
+    plugin = null;
+    super.stop(context);
+  }
+
+  /**
+   * Returns the shared instance
+   *
+   * @return the shared instance
+   */
+  public static Activator getDefault() {
+    return plugin;
+  }
+
+}
diff --git a/org.framed.orm.transformation/src/org/framed/orm/transformation/EpsilonStandalone.java b/org.framed.orm.transformation/src/org/framed/orm/transformation/EpsilonStandalone.java
new file mode 100644
index 00000000..217b5676
--- /dev/null
+++ b/org.framed.orm.transformation/src/org/framed/orm/transformation/EpsilonStandalone.java
@@ -0,0 +1,71 @@
+package org.framed.orm.transformation;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.eol.IEolExecutableModule;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.osgi.framework.Bundle;
+
+public abstract class EpsilonStandalone {
+
+  protected IEolExecutableModule module;
+
+  protected Object result;
+
+  public abstract IEolExecutableModule createModule();
+
+  public abstract String getSource();
+
+  public abstract List<IModel> getModels() throws Exception;
+
+  public void postProcess() {};
+
+  public void preProcess() {};
+
+  public void execute() throws Exception {
+
+    module = createModule();
+    module.parse(getTransformationFile());
+
+    if (module.getParseProblems().size() > 0) {
+      System.err.println("Parse errors occured...");
+      for (ParseProblem problem : module.getParseProblems()) {
+        System.err.println(problem.toString());
+      }
+      System.exit(-1);
+    }
+
+    for (IModel model : getModels()) {
+      module.getContext().getModelRepository().addModel(model);
+    }
+
+    preProcess();
+    result = execute(module);
+    postProcess();
+
+    module.getContext().getModelRepository().dispose();
+  }
+
+  protected Object execute(IEolExecutableModule module) throws EolRuntimeException {
+    return module.execute();
+  }
+
+  private URI getTransformationFile() {
+    Bundle bundle = Platform.getBundle("org.framed.orm.transformation");
+    URL fileURL = bundle.getEntry(getSource());
+
+    try {
+      return fileURL.toURI();
+    } catch (URISyntaxException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    return null;
+  }
+}
diff --git a/org.framed.orm.transformation/src/org/framed/orm/transformation/TransformationExecutor.java b/org.framed.orm.transformation/src/org/framed/orm/transformation/TransformationExecutor.java
new file mode 100644
index 00000000..f455cddd
--- /dev/null
+++ b/org.framed.orm.transformation/src/org/framed/orm/transformation/TransformationExecutor.java
@@ -0,0 +1,85 @@
+package org.framed.orm.transformation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.epsilon.emc.emf.EmfModel;
+import org.eclipse.epsilon.eol.IEolExecutableModule;
+import org.eclipse.epsilon.eol.dt.ExtensionPointToolNativeTypeDelegate;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.etl.EtlModule;
+
+public class TransformationExecutor extends EpsilonStandalone {
+
+  private Resource sourceModelFile;
+
+  private Resource targetModelFile;
+
+  private String transformationFile;
+
+  public TransformationExecutor() {
+    sourceModelFile = null;
+    targetModelFile = null;
+    transformationFile = "epsilon/ORM2CROM.etl";
+  }
+
+  public Resource getSourceModelFile() {
+    return sourceModelFile;
+  }
+
+  public void setSourceModelFile(Resource sourceModelFile) {
+    this.sourceModelFile = sourceModelFile;
+  }
+
+  public Resource getTargetModelFile() {
+    return targetModelFile;
+  }
+
+  public void setTargetModelFile(Resource targetModelFile) {
+    this.targetModelFile = targetModelFile;
+  }
+
+  public void setForcedTransformation(String transformationFileName) {
+    this.transformationFile = "epsilon/" + transformationFileName;
+  }
+
+  @Override
+  public IEolExecutableModule createModule() {
+    EtlModule module = new EtlModule();
+    module.getContext().getNativeTypeDelegates().add(new ExtensionPointToolNativeTypeDelegate());
+
+    return module;
+  }
+
+  @Override
+  public String getSource() {
+    return transformationFile;
+  }
+
+  @Override
+  public List<IModel> getModels() throws Exception {
+    List<IModel> models = new ArrayList<IModel>();
+
+    EmfModel emfModel = new EmfModel();
+    emfModel.setMetamodelUri("http://orm/1.0");
+    emfModel.setModelFileUri(sourceModelFile.getURI());
+    emfModel.setReadOnLoad(true);
+    emfModel.setStoredOnDisposal(true);
+    emfModel.setName("source");
+    emfModel.load();
+    models.add(emfModel);
+
+    emfModel = new EmfModel();
+    emfModel.setReadOnLoad(true);
+    emfModel.setModelFileUri(targetModelFile.getURI());
+    emfModel.setStoredOnDisposal(true);
+    emfModel.setMetamodelUri("platform:/resource/org.rosi.crom.metamodel/");
+    emfModel.setName("target");
+    emfModel.load();
+    models.add(emfModel);
+
+    return models;
+  }
+
+}
diff --git a/org.framed.orm.transformation/target/.gitignore b/org.framed.orm.transformation/target/.gitignore
new file mode 100644
index 00000000..840e7d31
--- /dev/null
+++ b/org.framed.orm.transformation/target/.gitignore
@@ -0,0 +1 @@
+/classes/
-- 
GitLab