Combining EMF Models with Xtext DSLs
This blog post demonstrates use cases on combining EMF models with Xtext DSLs. It is based on Martin Fowler's secret compartment state machine implementation available via the Xtext Example Wizard.
The meta-model of the statemachine language describes that a state machine consists of certain commands, events, states and transitions.
All these elements can be defined either in one dsl file, or can be split up into several *.statemachine files.
However, if we describe the commands and events in EMF models on the one hand and the states and transitions in an Xtext DSL on the other hand, the validation reports problems on the
fowler.statemachine file showing that the referenced commands and events cannot be resolved.
We would like to be able to reference EMF models from the Xtext DSL. Before starting adapting the productive code base, we capture our requirement in a StatemachineParsingTest test case.
Since we have a failing test now, we are allowed to extend the implementation. In order to be able to reference EMF models from an Xtext DSL, a new Xtext language has to be defined for the EMF resources. Thus, we define the
org.eclipse.xtext.example.fowlerdsl.emfstatemachine Xtext language for the
*.emfstatemachine resources using the following steps:
- For the new language, we define the runtime dependency injection container by adding the EmfStatmachineRuntimeModule class extending the AbstractGenericResourceRuntimeModule class. The AbstractGenericResourceRuntimeModule contains the default bindings for EMF resources, the EmfStatemachineRuntimeModule defines the language specific configurations such as the language name and the file extension.
- For the Eclipse-based UI services, we define the UI dependency injection container by adding the EmfStatemachineUiModule class extending the EmfUiModule class.
- We implement the FowlerDslActivatorEx class inheriting from the generated FowlerDslActivator class and register it in the MANIFEST.MF file to ensure that the EmfStatemachineRuntimeModule and EmfStatemachineUiModule classes are used while creating the injector of the newly defined Xtext language.
- In order to register the Xtext UI language services to the Xtext's registry, we implement the EmfStatemachineExecutableExtensionFactory that extends the AbstractGuiceAwareExecutableExtensionFactory. Last one delivers the bundle and the injector of the newly created Xtext language via the FowlerDslActivatorEx class. Additionally, we register the language in the plugin.xml via the
org.eclipse.xtext.extension_resourceServiceProviderextension point with the uriExtension
emfstatemachineand an instance of the EmfResourceUIServiceProvider created via the EmfStatemachineExecutableExtensionFactory class.
- Optionally, we can register the EmfStatemachineReflectiveTreeEditorOpener in the EmfStatemachineUiModule to open the EMF Reflective Tree Editor when the user follows a reference from the Xtext editor to an EMF element. To be able to use the EMF Reflective Tree Editor, we have to add the
org.eclipse.emf.ecore.editorplugin to the
Require-Bundlesection in the MANIFEST.MF file.
After implementing these steps, the successful execution of StatemachineParsingTest test case confirms that the EMF model references from the Xtext DSL can be resolved.
When starting the Eclipse Runtime again, the previously reported validation errors are also gone. Note that not only the validation, but also the content assistant and the quickfix provider are aware of the existing EMF model elements.
An additional feature could be to add Xtext serialization support to EMF models; when the user edits an EMF element and saves the *.emfstatemachine file, we want that the corresponding *.statemachine Xtext DSL file is automatically generated.
To achieve that, we implement the EmfStatemachineSerializer class and bind it in the EmfStatemachineRuntimeModule class. Furthermore, the EmfStatemachineSerializationHandler class registered in the plugin.xml triggers the manual conversion from EMF to Xtext via the
Serialize EMF State-Machine with Xtext context menu of the Package/Project Explorer.
If you would like to learn more about the Xtext-EMF integration, I recommend looking into Karsten and Holger's presentation on How to build Code Generators for Non-Xtext Models with Xtend.