Last year we presented a paper with the title “Interchange of (Meta)Models between MetaEdit+ and Eclipse EMF using M3-Level-Based Bridges” at the OOPSLA Workshop on Domain-Specific Modeling. The paper describes the application of the M3B approach to MetaEdit+ and the Eclipse Modeling Framework. Analogous to the Visio-EMF-Bridge or the ARIS-EMF-Bridge, the MetaEdit-EMF-Bridge is based on a mapping between their metametamodels (in this case: GOPPRR from MetaEdit+ and Ecore from EMF). Starting from this GOPPRR-Ecore mapping (at M3-level), transformations can be derived at metamodel level (M2) and model level (M1). In this article we want to demonstrate the bridge with some practical examples in order to illustrate the potential of this bridge. We select three simple use cases: (1) the generic model exchange itself, (2) a code generation example with XPand, and (3) a model-to-model-transformation example with XTend.
(1) Generic Model Exchange
The MetaEdit-EMF-Bridge enables the transformation of any MetaEdit+ model into an EMF model and vice versa with one constraint. This constraint is caused by the fact that we can only transform metamodels from MetaEdit+ into EMF. The reverse direction from EMF to MetaEdit+ is theoretically also possible, but for technical reasons not implemented until now. To transform EMF models into MetaEdit+ models, we need to assure that the EMF models conform to a previously exported MetaEdit+ metamodel.
In this example we want to focus on the exchange of models itself. Hence, we select a simple metamodel and a model that should be transformed. Figure 1 illustrates such a metamodel with the MetaEdit-specific notation. This metamodel defines a part of the EPC language and contains the following concepts:
- Graph type: Event-Driven Process Chain,
- Objects types: Node, Event, Function, Connector, AND, XOR, OR,
- Property: Name,
- Port: -
- Relationship type: Arc,
- Role types: From, To.
We export this metamodel as an XML file and we take this file as input for our M2-level transformation. The result of the M2-level transformation is the EMF metamodel in Figure 2. Each graph, object, relationship and role is transformed into an EClass and each property is transformed into an EAttribute. The name of each EClass is composed of the name and the unique id of the corresponding MetaEdit+ element. Furthermore, each EClass is inherited from an EClass that corresponds to a GOPPRR concept. For instance, all EClasses that are Object types are inherited from the EClass Me_Object. To support roundtrip, we annotate each EMF element with MetaEdit-specific information that allows the correct re-instantiation in MetaEdit+.
After the transformation of the metamodel from MetaEdit to EMF, we can transform an EPC model, such as the one in Figure 3. The M1-level transformation uses the SOAP API from MetaEdit+ in order to read the model data. The result of the transformation is the EMF model in Figure 4. The result of the roundtrip transformation is the same as the original model in Figure 3. Currently, the import of EMF models in MetaEdit+ creates new MetaEdit+ elements, as we don’t support a merging strategy.
For a better understanding of the whole import and export process, you can see the following video: ->Video: Generic model exchange.
(2) Code Generation: UML to Java
In this section we want to illustrate, how we can generate Java code from an UML class diagram that has been modeled in MetaEdit+. Figure 5 shows this UML class diagram conforming to the already existing UML metamodel in MetaEdit+ (see UML project in MetaEdit+). Figure 6 represents the transformed EMF model.
The generator is described in the following XPand template. The main block (line 6-10) selects all UML class diagrams and calls the ClassDiagram block (line 12-16). This ClassDigram block calls the Class block (line 18-25) for each class element. This Class block creates a Java class file with the name of the UML class, iterates over all attributes, and creates for each attribute a variable with getters and setters.
«IMPORT gopprr» «IMPORT gopprr::metamodel» «EXTENSION template::Association» «DEFINE main FOR Me_Project» «EXPAND ClassDiagram FOREACH (Collection[Class_Diagram__UML__3019387957])this.me_containGraphs. select(e|e.metaType == Class_Diagram__UML__3019387957)» «ENDDEFINE» «DEFINE ClassDiagram FOR Class_Diagram__UML__3019387957» «EXPAND Class FOREACH (Collection[Class__UML__3019392012])this.me_referenceObjects. select(e|e.metaType == Class__UML__3019392012)» «ENDDEFINE» «DEFINE Class FOR gopprr::metamodel::Class__UML__3019392012» «FILE this.Class_name + ".java"» public class «this.Class_name» { «EXPAND Attribute FOREACH this.Attributes» } «ENDFILE» «ENDDEFINE» «DEFINE Attribute FOR gopprr::metamodel::Attribute__UML__3019390346» «this.Visibility» «this.Data_type» «this.Name»; public void set«this.Name.toFirstUpper()»(«this.Data_type» «this.Name») { this.«this.Name» = «this.Name»; } public «this.Data_type» get«this.Name.toFirstUpper()»() { return this.«this.Name»; } «ENDDEFINE»
The following Java class shows the result of the generation. It is one of the three generated classes. The other two classes (Library and Writer) are analog to this class.
public class Book { public String title; public void setTitle(String title) { this.title = title; } public String getTitle() { return this.title; } public int page; public void setPage(int page) { this.page = page; } public int getPage() { return this.page; } }
The complete generation process is shown in the following video: ->Video: Code generation: UML to Java.
(3) Model transformation: EPC to BPMN
In this example we want to transform EPC models into BPMN models. We use the EPC model in Figure 3 as input. After we have transformed the EPC metamodel and BPMN metamodel from MetaEdit+ into EMF, we can transform this EPC model from MetaEdit+ into EMF. Now we can use XTend to implement the model-to-model transformation. The following XTend script shows the transformation definition. Note, that we can only transform EPC models with sequences in order to keep the example simple. The first part (line 2-19) of the script creates a MetaEdit+ project and adds the transformed elements to this project. The second part (line 22-47) describes the transformation between different language concepts. For instance, we map: (EPC) start event -> (BPMN) start, (EPC) end event -> (BPMN) end, and (EPC) function -> (BPMN) task. The last part creates the concrete syntax in form of a diagram.
//creates the project create Me_Project transform(Me_Project inputModel) : this.me_containGraphs.addAll(inputModel.getEpcModels().createBpmnGraph(this)); create BPMN_3356593652 createBpmnGraph(Event_Driven_Process_Chain_3395083925 epcGraph, Me_Project epcModel) : this.setModel_name(epcGraph.Name) -> this.me_referenceObjects.addAll(epcGraph.getEpcStartEvents().createBpmnStart()) -> epcModel.me_containObjects.addAll(epcGraph.getEpcStartEvents().createBpmnStart())-> this.me_referenceObjects.addAll(epcGraph.getEpcEndEvents().createBpmnEnd()) -> epcModel.me_containObjects.addAll(epcGraph.getEpcEndEvents().createBpmnEnd()) -> this.me_referenceObjects.addAll(epcGraph.getEpcFunctions().createBpmnTask()) -> epcModel.me_containObjects.addAll(epcGraph.getEpcFunctions().createBpmnTask()) -> this.me_referenceRelationships.addAll(epcGraph.getEpcArc().createBpmnSequence(epcGraph)) -> epcModel.me_containRelationships.addAll(epcGraph.getEpcArc().createBpmnSequence(epcGraph)) -> this.me_referenceRoles.addAll(epcGraph.getEpcTo().createBpmnTo(epcGraph)) -> epcModel.me_containRoles.addAll(epcGraph.getEpcTo().createBpmnTo(epcGraph)) -> this.me_referenceRoles.addAll(epcGraph.getEpcFrom().createBpmnFrom(epcGraph)) -> epcModel.me_containRoles.addAll(epcGraph.getEpcFrom().createBpmnFrom(epcGraph)) -> this.me_containDiagrams.add(epcGraph.createBpmnGraph(epcModel).createDiagram()); //transformation rules create Start_3356593122 createBpmnStart(Event_3395083771 epcEvent) : this.setEvent_name(epcEvent.Name); create End_3356599528 createBpmnEnd(Event_3395083771 epcEvent) : this.setEvent_name(epcEvent.Name); create Task_3356599626 createBpmnTask(Function_3395083784 epcFunction) : this.setTask_name(epcFunction.Name); create Sequence_flow_3356602558 createBpmnSequence(Arc_3395083800 epcArc, Event_Driven_Process_Chain_3395083925 epcGraph) : this.me_role.addAll( ((List[To_3395083810])epcArc.me_role.select(e|e.metaType==To_3395083810)).createBpmnTo(epcGraph) ) -> this.me_role.addAll( ((List[From_3395083804])epcArc.me_role.select(e|e.metaType==From_3395083804)).createBpmnFrom(epcGraph) ); create To_3356600495 createBpmnTo(To_3395083810 epcTo, Event_Driven_Process_Chain_3395083925 epcGraph) : epcTo.me_object.isStartEvent(epcGraph) ? this.setMe_object( ((Event_3395083771)epcTo.me_object).createBpmnStart() ) : Void -> epcTo.me_object.isEndEvent(epcGraph) ? this.setMe_object( ((Event_3395083771)epcTo.me_object).createBpmnEnd() ) : Void -> epcTo.me_object.metaType==Function_3395083784 ? this.setMe_object( ((Function_3395083784)epcTo.me_object).createBpmnTask()) : Void; create From_3356600480 createBpmnFrom(From_3395083804 epcFrom, Event_Driven_Process_Chain_3395083925 epcGraph) : epcFrom.me_object.isStartEvent(epcGraph) ? this.setMe_object( ((Event_3395083771)epcFrom.me_object).createBpmnStart() ) : Void -> epcFrom.me_object.isEndEvent(epcGraph) ? this.setMe_object( ((Event_3395083771)epcFrom.me_object).createBpmnEnd() ) : Void -> epcFrom.me_object.metaType==Function_3395083784 ? this.setMe_object( ((Function_3395083784)epcFrom.me_object).createBpmnTask()) : Void; create Me_Diagram createDiagram(Me_Graph meGraph) : this.me_containSymbols.addAll(meGraph.me_referenceObjects.createSymbol()); create Me_Symbol createSymbol(Me_Object meObject) : this.setMe_refObject(meObject);
The result of the transformation is shown in Figure 7. In our transformation we ignore the position of the BPMN elements. Hence, the position of the BPMN elements doesn’t correspond with the origin position of the EPC elements. You can see the complete transformation in the following video: ->Video: Model transformation: EPC to BPMN.
Summary
In this article we have demonstrated a prototypical adapter that allows the exchange of any model between MetaEdit+ and Eclipse EMF. The three examples show the functionality and the possible applications of the adapter. From our point of view, the combination of MetaEdit+ and the Eclipse world is very useful because it extends MetaEdit+ with powerful tools and functionality in order to solve typical DSM/MDD tasks, such as transformation, generation, or validation – to name a few. We also know that MetaEdit+ has its own model processing language (MERL) which covers many of these tasks. However, we are convinced that some tasks can be “better” solved through Eclipse-based tools (oAW, Epsilon, ATL, etc.) than with MERL. A proof of this statement would be really interesting! Maybe this is stuff for another article with the title “MERL vs. oAW”.
Download
- Video: Generic model exchange
- Video: Code generation: UML to Java
- Video: Model transformation: EPC to BPMN
- Source code: Examples
- Source code: MetaEdit-EMF-Bridge
We tested the MetaEdit-EMF-Bridge with Eclipse 3.4, EMF 2.4, and the exmaples run with oAW 4.3.1.









Hi Heiko, nice post! It’s great to see all of your integration work so well presented here. Your idea for an article “MERL vs. oAW” sounds interesting, although maybe just “MERL and oAW” is less combative and indeed truer, since they’re actually really similar. I’ve posted the corresponding (if somewhat shorter!) MERL code for your UML->Java example on my blog:
http://www.metacase.com/blogs/stevek/blogView?showComments=true&entry=3428923761
Maybe you want to take me up on my challenge about generator performance too?
http://www.metacase.com/blogs/stevek/blogView?showComments=true&entry=3385914921
Hello Steven, thank you for your nice comment! I agree with you that “versus” sounds a little bit provocative. But I wanted to lay emphasis on the comparison idea between oAW and MERL. That’s why, I used “MERL vs. oAW” instead of “MERL and oAW”. Anyway, I think, the idea of a comparison between different DSM/MDD tools could be very exciting and helpful. Furthermore, I’ve read your reply to my article and posted some comments on your blog.
http://www.metacase.com/blogs/stevek/blogView?showComments=true&entry=3428923761