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