Tutorial
on embedding Xtext editors inside Papyrus diagrams Version 0.6
|
Papyrus Tutorial:
How to embed an Xtext editor inside a Papyrus diagram
Editor |
Saadia DHOUIB, Arnaud CUCCURU, Vincent LORENZO - CEA LIST |
Status |
Production |
Version number |
0.4 |
Date of preparation |
2010-07-08 |
Authors name (first/last name) |
Company |
|
Initial |
Saadia DHOUIB |
CEA LIST |
SD |
|
Arnaud CUCCURU |
CEA LIST |
AC |
Version |
Date |
Reasons |
0.1 |
18/05/10 |
Initial contribution. |
0.2 |
03/06/10 |
Sections 1, 2, 3 finished |
0.3 |
04/06/10 |
Section 4, 5 finished |
0.4 |
08/07/10 |
Modified section 1, Moved 3.2.e (extending the directEditors extension point) to section 5, cosmectic/english modifications |
0.5 |
12/07/10 |
Section 5 modified, papyrus icon changed (p1) |
0.6 |
10/01/10 |
Adds Section 6 : Code enhancements |
Authors 2
Revision chart and history log 3
Table of contents 4
2 How to install eclipse Xtext bundle for Papyrus development 6
3 Create and configure your Xtext project 8
3.2 Configure the Xtext project for using UML models 11
Xtext is a framework for the development of domain-specific languages and other textual programming languages. It is tightly integrated with the Eclipse Modeling Framework (EMF) and leverages the Eclipse Platform in order to provide a language-specific integrated development environment (IDE).
The purpose of this document is to provide a tutorial for Papyrus users and developers, explaining the followings:
how to install and configure the xtext eclipse bundle for papyrus development
how to create and configure an xtext project
how to build an xtext grammar
how to develop an xtext editor integrated in a papyrus UML diagram
Install the latest version of Eclipse Helios.
In order to install Papyrus and Xtext, go to the menu: Help -> Install Modeling Component. Then select Papyrus and Xtext, and press Finish.
Figure 1: Papyrus and
Xtext installation
Use the Xtext wizard to create a new project: File -> New -> Project... -> Xtext -> Xtext project (cf. Figure 2)
Figure
2: Choose Xtext wizard
Main project name: |
org.eclipse.papyrus.message.editor.xtext |
Language name: |
org.eclipse.papyrus.message.editor.xtext.UmlMessage |
DSL-File extension: |
umlmessage |
Keep “Create generator project” checked, as we will also create a code generator in a second step (cf. Figure 3). Click on Finish to create the projects.
By convention, the following naming pattern is followed:
Project name: 'org.eclipse.papyrus' <kind of the element to be edited> 'editor.xtext'
Language name: <Project name> 'Uml' <Kind of the element to be edited>
DSL-File extension: 'uml' <kind of the element to be edited>
Figure
3: Create new xtext project
Figure 3 provides an example related to the creation of a textual editor for Messages, in the context of communication diagrams.
Project Layout:
In the Package Explorer you can see
three new projects (cf. Figure 4). In
org.eclipse.papyrus.message.editor.xtext
you can define
the grammar and configure the runtime aspects of your language. The
editor, outline view and code completion goes into
org.eclipse.papyrus.message.editor.xtext.ui
. Both
projects consist of generated classes derived from your grammar and
manual code such as the grammar itself or further classes to
differentiate from the default behavior.
Figure
4: Xtext project layout
It is good to be clear and unambiguous whether the code is generated or is to be manipulated by the developer. Thus, the generated code should be held separately from the manual code. We follow this pattern by having a folder src/ and a folder src-gen/ in each project. Keep in mind not to make changes in the src-gen/ folder. They will be overwritten by the generator.
Build the generated sample
grammar: The wizard will automatically open the example grammar file
UmlMessage.xtext
from the first project in the editor.
We will test the generation of the language artifacts. To do this,
locate the file GenerateUmlMessage.mwe next to the grammar file in
the package explorer view (cf. Figure 5). From its context menu,
choose Run As -> MWE Workflow. That will trigger the
Xtext language generator. You will see its logging messages in the
Console view. No errors should appear in the Console view. The
purpose of this step is to obtain the file plugin.xml that will be
modified in the next step.
Figure
5: Generate language artifacts
Papyrus projects are based on UML2 models. To combine the xtext defined grammar with the existing UML2 model, it is necessary to do the following steps:
The first thing we have to do is to add two additional dependencies to the eclipse xtext project (org.eclipse.papyrus.message.editor.xtext) :
org.eclipse.uml2.codegen.ecore (1.0.6)
org.eclipse.uml2.uml (3.1.0)
To do this, open the file plugin.xml (generated previously) and add the aforementioned dependencies (cf. Figure 6).
Figure
6: Adding plugin dependencies
The models are integrated in the eclipse environment. For a standalone usage they have to be copied to the xtext project. Add a new folder “model” and add the following model files to it (cf. Figure 7):
UML.genmodel
UML.ecore
Ecore.ecore
Ecore.genmodel
Figure
7: Add files to model folder
The grammar must gain knowledge about the UML2 metamodel. This can be done with the following import in the UmlMessage.xtext grammar file:
import "http://www.eclipse.org/uml2/3.0.0/UML" as uml
Figure 8 illustrates this import.
Figure
8: import UML2 metamodel in the xtext grammar file
With the alias uml the UML2 model elements can be used in the grammar, such as shown below:
NameRule: name=ID
':'
((type=[uml::Classifier])
| "<Undefined>")
In this example, the statement “type=[uml::Classifier]” specifies that the property “type” of rule “NameRule” is used to specify a reference to an existing UML Classifier. By specifying this kind of rule, the Xtext framework is able to generate tools for completion, content assist and cross references to Classifiers available in the Scope of the rule.
Modify the GenerateUmlMessage.mwe2 file:
The packages “UMLPackage” and “GenModelPackage” have to be setup. This allows the generator to resolve the uris. The original uri references point to the plugins environment, so a uri mapping helps the generator. You have to add the following code in the GenerateUmlMessage.mwe2 file:
bean
= StandaloneSetup { platformUri
= "${runtimeProject}/.." registerGeneratedEPackage
= "org.eclipse.uml2.uml.UMLPackage" registerGeneratedEPackage
= "org.eclipse.uml2.codegen.ecore.genmodel.GenModelPackage" uriMap
= {from="platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore"
to="platform:/resource/org.eclipse.papyrus.message.editor.xtext/model/Ecore.ecore"} uriMap
=
{from="platform:/plugin/org.eclipse.emf.ecore/model/Ecore.genmodel"
to="platform:/resource/org.eclipse.papyrus.message.editor.xtext/model/Ecore.genmodel"} }
Figure 9 shows the exact place where this code has to be added.
Figure
9: Modify the mwe2 file to setup “UMLPackage” and
“GenModelPackage”
Then, add a hint for the model generation to EcoreGeneratorFragment fragment (Figure 10). So the generator can use the UML2 API.
Figure
10: Adding a hint for the model generation to EcoreGeneratorFragment
Finally you have to change the scoping and exporting part in the mwe2 file, following the code below:
//
scoping and exporting API fragment
= scoping.ImportURIScopingFragment {} fragment
= exporting.SimpleNamesFragment {} //
scoping and exporting API
/*fragment
= scoping.ImportNamespacesScopingFragment {} fragment
= exporting.QualifiedNamesFragment {} */
Many tutorials on the web can help you to create your grammar [1, 2].
Important note: Avoid the usage of terminal rules if one part of the regular expression is semantically relevant (e.g., in our example, the rule SequenceTermRule could be fully captured by a simple regular expression). In order to ease the usage of semantically relevant information (e.g., in our exemple, the property sequencialorder or rule SequenceTermRule), you should use data type rules or parser rules. In the example below, we show the grammar of the UMLMessage label.
grammar
org.eclipse.papyrus.message.editor.xtext.UmlMessage with
org.eclipse.xtext.common.Terminals
import
"http://www.eclipse.org/uml2/3.0.0/UML"
as
uml generate
umlMessage
"http://www.eclipse.org/papyrus/message/editor/xtext/UmlMessage" MessageRule:
sequenceTerm
+= SequenceTermRule
('.'
sequenceTerm += SequenceTermRule)* ':' name
= nameRule ; SequenceTermRule
: sequencialOrder
= INT //represents the sequential order
of the Message within the next higher level of procedural calling (sequenceName
= ID)? // represents a concurrent
thread of control. Messages that differ in the final name are
concurrent at that level of nesting (recurrence
= RecurrenceRule)? // The recurrence
represents conditional or iterative execution. ; terminal
nameRule: ('a'..'z'|'A'..'Z')
('a'..'z'|'A'..'Z'|'_'|'-'|'0'..'9')*; RecurrenceRule
:
('*'
'['
STRING ']')|('['
STRING ']')
;
Once you have created your grammar, you can :
generate language artifacts: Save the grammar and make sure that no error markers appear. Then, locate the file GenerateUMLMessage.mwe next to the grammar file in the package explorer view. From its context menu, choose Run As -> MWE Workflow. That will trigger the Xtext language generator. You will see its logging messages in the Console view.
Run the generated editor: If code generation succeeded, right-click on the Xtext project and choose Run As -> Eclipse Application. This will spawn a new Eclipse workbench with your projects as plug-ins installed. In the new workbench, create a new project ( File -> New -> Project... -> General -> Project) and therein a new file with the file extension you chose in the beginning. This will open the generated entity editor.
Once you have created and tested your grammar, you can go to the next step which is embedding the XtextEditor inside a pop up Editor.
In order to enable the encapsulation of the Xtext editor inside a Papyrus diagram, the org.eclipse.papyrus.message.editor.xtext.ui plugin has to contribute to a papyrus extension point: org.eclipse.papyrus.extensionpoints.editors.DirectEditor:
Select plugin.xml in the org.eclipse.papyrus.message.editor.xtext.ui project. Go to Dependencies corner, and add a dependency to org.eclipse.papyrus.extensionpoints.editors, as shown in Figure 11.
Figure
11: Adding dependency to
org.eclipse.papyrus.extensionpoints.editors
Go to Extensions corner, and add a new extension which is org.eclipse.papyrus.extensionpoints.editors.DirectEditor (cf. Figure 12).
Figure
12: Add new extension
Edit this extension by: (cf. Figure 13)
Setting the language name (e.g., Advanced message editor)
Setting the kind of element to edit (in this example, org.eclipse.uml2.uml.Message)
Setting the contributer (here, CEA List)
Figure
13: Editing the extension details
Select the previously created extension org.eclipse.uml2.uml.Message (DirectEditor), right click on and choose “New popup editor”. In the extension Element Details corner, select 'editor configuration', and set the name of the package and the class as shown in Figure 14. Before that, you are supposed to create the package org.eclipse.papyrus.message.editor.xtext.ui.contributions in the src folder of the project org.eclipse.papyrus.message.editor.xtext.ui .
Figure
14: Set the editor configuration
The created class MessagePopupEditor, have to extend org.eclipse.xtext.gmf.glue.PopupEditorConfiguration class.
The latter class is provided in the org.eclipse.xtext.gmf.glue plug-in.
The two methods that you have to customize inside the MessagePopupEditorConfigurationContribution class are:
getTextToEdit: this method returns the string that will be edited inside the popup editor.
createPopupEditorHelper: this method is responsible for displaying the Xtext popup editor...
Some other classes have to be created in the src folder of the org.eclipse.papyrus.message.editor.xtext.ui and org.eclipse.papyrus.message.editor.xtext projects:
org.eclipse.papyrus.state.editor.xtext.ui.editor.ContextEditorUtil: this class is responsible for saving the context of the current editor
org.eclipse.papyrus.message.editor.xtext.scoping.UmlMessageScopeProvider: this class is responsible for providing an Iscope for a given context EObject and EReference. The returned IScope should contain all target candidates for the given object and cross-reference.
A new Xtext project has been created in order to regroup common code.
org.eclipse.papyrus.common.editor.xtext
org.eclipse.papyrus.common.editor.xtext.generator
org.eclipse.papyrus.common.editor.xtext.ui
org.eclipse.papyrus.common.editor.xtext
This plugin provides grammar for :
QualifiedName
Direction
VisibilityKind
MultiplicityRule
BoundsSpecification
UnlimitedNatural
TypeRule
To use it :
1/ in the file plugin.xml of your plugin editor.xtext, adds the dependency to org.eclipse.papyrus.common.editor.xtext
2/ in your grammar file replaces
grammar
org.eclipse.papyrus.myelement.editor.xtext.UmlMessage with
org.eclipse.xtext.common.Terminals
by
grammar
org.eclipse.papyrus.parameter.editor.xtext.UmlParameter
//with
org.eclipse.xtext.common.Terminals with
org.eclipse.papyrus.common.editor.xtext.UmlCommon
3/ In the GenerateUmlElement.mwe2, replace the following line :
//
generates Java API for the generated EPackages
fragment
= ecore.EcoreGeneratorFragment { referencedGenModels
=
"platform:/resource/org.eclipse.papyrus.myelement.editor.xtext/model/UML.genmodel" }
by :
//
generates Java API for the generated EPackages
fragment
= ecore.EcoreGeneratorFragment { referencedGenModels
=
"platform:/resource/org.eclipse.papyrus.myelement.editor.xtext/model/UML.genmodel" referencedGenModels
=
"platform:/resource/org.eclipse.papyrus.common.editor.xtext/src-gen/org/eclipse/papyrus/common/editor/xtext/UMLCommon.genmodel" }
This plugin provides some classes which can be extended in the other Xtext plugin :
UmlCommonJavaValidator
UmlCommonScopeProvider (methods to naviagate in Namespace)
org.eclipse.papyrus.common.editor.xtext.generator
Not used.
org.editor.papyrus.common.editor.xtext.ui
In the project org.eclipse.papyrus.myelement.editor.xtext.ui adds the dependency to org.editor.papyrus.common.editor.xtext.ui.
This plugin provides some classes which can be extended in other Xtext plugin :
- UmlCommonProposalProvider
[1] Xtext tutorial, http://www.eclipse.org/Xtext/documentation/latest/xtext.html#getting-started
[2] Xtext Reference document, http://www.eclipse.org/Xtext/documentation/0_7_2/xtext.pdf,2009
2010 The
Papyrus Consortium