Eclipse, Xtext, DSL, english, Software Development

How to reference UML elements from Xtext DSLs

With the Xtext framework, you can build DSL workbenches in just a few steps. However, sometimes you want to reuse model elements already defined in other formats or even in other languages. In this blog post I’m going to demonstrate typical scenarios when you’re reusing model elements belonging to a different language.

Firstly, consider having some pre-defined Eclipse UML2 models, and you want to reference classes of these UML models from your Xtext DSL.

If you are interested in reusing model elements belonging to the same language but defined in different formats, take a look at my previous blog post “Combining EMF models with Xtext DSLs”.

Let's get started with the preparatory steps:

Preparatory steps

  1. Install the latest version of the UML2 Extender SDK and the Xtext Complete SDK of the Eclipse release train.

    install-Xtext-Complete-SDK-and-UML2-Extender-SDK

     

  2. Create the Domainmodel project, based on the Xtext 15 Minutes Tutorial. The meta-model of the Domainmodel project

    meta-model-of-the-Domainmodel project

    describes that a domain model consist of certain types (data types and entities), an entity contains features and each feature can have a type. To be able to use UML classes in the feature's type definition, the following modifications are necessary:

Modifications1 in the org.example.domainmodel plug-in

  1. Extend the Domainmodel.xtext grammar definition:
    grammar org.example.domainmodel.Domainmodel with org.eclipse.xtext.common.Terminals
    
    ...
    
    import "http://www.eclipse.org/uml2/5.0.0/UML" as uml
    
    ...
    
    Feature:
    	(many?='many')? name=ID ':' type=[uml::Class|FQN] | type=[Type];
    
    ...

     

  2. Extend the GenerateDomainmodel.mwe2 workflow:
    module org.example.domainmodel.GenerateDomainmodel
    
    import org.eclipse.emf.mwe.utils.*
    import org.eclipse.xtext.xtext.generator.*
    import org.eclipse.xtext.xtext.generator.model.project.*
    
    var rootPath = ".."
    
    Workflow {
    
    	bean = StandaloneSetup {
    		
    		scanClassPath = true
    		platformUri = rootPath
    		
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.emf.codegen.ecore/model/GenModel.genmodel"
    			to = "platform:/resource/org.eclipse.emf.codegen.ecore/model/GenModel.genmodel"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.emf.ecore/model/Ecore.genmodel"
    			to = "platform:/resource/org.eclipse.emf.ecore/model/Ecore.genmodel"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.uml2.codegen.ecore/model/GenModel.genmodel"
    			to = "platform:/resource/org.eclipse.uml2.codegen.ecore/model/GenModel.genmodel"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.uml2.uml/model/UML.genmodel"
    			to = "platform:/resource/org.eclipse.uml2.uml/model/UML.genmodel"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.emf.codegen.ecore/model/GenModel.ecore"
    			to = "platform:/resource/org.eclipse.emf.codegen.ecore/model/GenModel.ecore"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.emf.ecore/model/Ecore.ecore"
    			to = "platform:/resource/org.eclipse.emf.ecore/model/Ecore.ecore"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.uml2.codegen.ecore/model/GenModel.ecore"
    			to = "platform:/resource/org.eclipse.uml2.codegen.ecore/model/GenModel.ecore"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.uml2.uml/model/UML.ecore"
    			to = "platform:/resource/org.eclipse.uml2.uml/model/UML.ecore"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.uml2.types/model/Types.genmodel"
    			to = "platform:/resource/org.eclipse.uml2.types/model/Types.genmodel"
    		}
    		uriMap = {
    			from = "platform:/plugin/org.eclipse.uml2.types/model/Types.ecore"
    			to = "platform:/resource/org.eclipse.uml2.types/model/Types.ecore"
    		}
    		
    		registerGeneratedEPackage = "org.eclipse.emf.ecore.EcorePackage"
    		registerGeneratedEPackage = "org.eclipse.uml2.uml.UMLPackage"
    		registerGeneratedEPackage = "org.eclipse.uml2.types.TypesPackage"
    		registerGeneratedEPackage = "org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage"
    		registerGeneratedEPackage = "org.eclipse.uml2.codegen.ecore.genmodel.GenModelPackage"
    		registerGenModelFile = "platform:/resource/org.eclipse.emf.ecore/model/Ecore.genmodel"
    		registerGenModelFile = "platform:/resource/org.eclipse.emf.codegen.ecore/model/GenModel.genmodel"
    		registerGenModelFile = "platform:/resource/org.eclipse.uml2.uml/model/UML.genmodel"
    		registerGenModelFile = "platform:/resource/org.eclipse.uml2.codegen.ecore/model/GenModel.genmodel"
    	}
    	
    	component = XtextGenerator {
    		...
    	}
    }

     

  3. Add the following plugins to the Require-Bundle section in the MANIFEST.MF file:
    • org.eclipse.uml2.uml
    • org.eclipse.uml2.codegen.ecore
  4. Add the following classes:

Modifications2 in the org.example.domainmodel.ui plug-in

  1. Add the following classes:
  2. Register DomainmodelActivatorEx as Bundle-Activator in the MANIFEST.MF file.
  3. Add the following plugin to the Require-Bundle section in the MANIFEST.MF:
    • org.eclipse.emf.ecore.editor
  4. Add the following section to the plugin.xml file:
    <!-- register the Xtext UI language services to Xtext's registry -->
    <extension
    	point="org.eclipse.xtext.extension_resourceServiceProvider">
    	<resourceServiceProvider
    		class="org.example.domainmodel.ui.UMLExecutableExtensionFactory:org.eclipse.xtext.ui.resource.generic.EmfResourceUIServiceProvider"
    		uriExtension="uml">
    	</resourceServiceProvider>
    </extension>

     

Manual testing

Start an Eclipse runtime to verify that parsing, linking, content assistant, hovering, hyperlink navigation, quickfixes, etc., are working properly.

Eclipse-manual-testing

Automated testing

Conclusion

We have done the preparatory steps, modifications and testing necessary to reuse model elements belonging to a different language. This example has been kept simple on purpose.

If you are interested in more advanced use-cases on the Xtext/UML integration, I recommend Karsten‘s and Holger‘s presentation on “How to build Code Generators for Non-Xtext Models with Xtend”.

Do you have questions or feedback? Feel free to leave me a comment below.

 


1,2 Please note that the blog post “Combining EMF Models with Xtext DSLs” explains the necessary modifications in detail.

   
About Tamas Miklossy

Tamas works as an IT consultant at itemis AG in Lünen. He is interested in model-driven software development, especially in graphical and textual modeling solutions.