-
Notifications
You must be signed in to change notification settings - Fork 4
Creating a Textual Editor
The goal of this page is to create a textual editor for a chosen diagram type that you can integrate in the Cooperate Modeling Environment. The required steps include
- Definition and implementation of a grammar and a meta model
- Implementation of state calculators
- Implementation of automated issue resolutions
- Implementation of outline
- Implementation of comparator for CDO
-
Xtext
- Textual editor framework
- Important topics: Grammar, quickfixes, validation, outline
-
EMF
- Modeling framework for Eclipse
- Important topics: Creating a meta model, generating code
-
UML 2.5
- Official UML standard
- Important topics depend on the chosen diagram type, you should read this on demand
The meta model defines the structure of the information displayed in your textual syntax. When working with Xtext, the structure of your meta model and your grammar are tigthly coupled. Therefore, it might be necessary to adjust the meta model and grammar together if you want to change anything.
First of all, you have to create a new plugin project:
- Create a plugin project that will include the meta model (it is best practice to name the project ...activity.metamodel if you create a meta model for an activity diagram)
- Choose Eclilpse as the target platform in the wizard and do not change the default version
- Create a new folder
model
- Add a dependency to
de.cooperateproject.modeling.textual.common.metamodel
Afterwards, you can create the meta model in the model
folder:
- Set the name, ns prefix and ns uri of the root package
- Load the textual commons resource
- If the textual commons meta model is installed, use the registered packages and look for
http://www.cooperateproject.de/modeling/textual/commons
- If the textual commons meta model is located in your workspace, use the workspace browser and select the ecore model
- If the textual commons meta model is installed, use the registered packages and look for
- For every non-artificial parser rule in your grammar, create a concrete EClass
- For every feature in your grammar, create an according EStructuralFeature
- Use the base classes of the textual commons meta model whenever possible
- Every concrete EClass that has a counterpart in the UML meta model has to (transitively) extend the UMLReferencingElement EClass
- Add interfaces, abstract classes, and relations to improve the structure of your meta model (e.g. to introduce reasonable inheritance structures)
Next, you have to create the generator model with the same name in the model
folder:
- Create a new EMF generator model from the wizard
- Give it the file name as the ecore model
- Choose
Ecore model (CDO Native)
- Select your newly created ecore model
- Select the root package of your ecore model as root package
- Select all other referenced models in the bottom area of the dialog page
- Open the generator model
- Select the root element
- change the
Feature Delegation
in the groupModel
toDynamic
- change the
Model Directory
in the groupModel
from.../src
to.../src-gen
- change the
- Select the first entry under the root element
- set the
Base Package
in the groupAll
to the name of your plugin project
- set the
- Select the root element
- Open the generator model in a text editor
- For all entries in the
usedGenPackages
attribute, replace../../
withplatform:/plugin/
- For all entries in the
Finally, you should generate the code for model, edit, and editor plugins with the generator model. You have to regenerate the code everytime you change the model.
Before designing your grammar, please have a look at our general syntax guidelines and existing syntaxes. Additionally, you have to choose relevant elements for your diagram and omit elements that are not essential or that are rarely used.
First, you should create a new Xtext project.
- Select
Xtext Project From Existing Ecore Models
in the new wizard - Select the generator model you created in the step before
- Choose your entry rule (usually you want to choose the XYDiagram element)
- Use the project name that you used for the meta model plugin but omit the
.metamodel
- Use a short file extension (usually 3 digits) such as abbreviations suggested in the UML 2.5 standard Annex A
- Use the same name like the project name but append the diagram abbreviation
- Keep all settings regarding plugin generation as it is
- After pressing finish, 5 projects should have been created
In the next step, you can fix the errors in the generated grammar file:
- Delete all existing rules and start over
- Replace all import statements that are marked with the platform resource URI
- old:
import "http://www.cooperateproject.de/modeling/textual/cls/Cls"
- new:
import "platform:/resource/de.cooperateproject.modeling.textual.cls.metamodel/model/cls.ecore"
- old:
In order to generate code from your grammar file, you have to use the MWE2 workflow. Adjust the workflow in order to generate the code required for integration in the Cooperate Modeling Environment. You can use the template given below. Do not forget to replace every placeholder in angle brackets.
module <module qualifier, just keep it>
import org.eclipse.xtext.xtext.generator.*
import org.eclipse.xtext.xtext.generator.model.project.*
import de.cooperateproject.modeling.textual.xtext.generator.*
var rootPath = ".."
var basename = "<the base package you chose in the generator model when defining the meta model>"
Workflow {
bean = org.eclipse.emf.mwe.utils.StandaloneSetup {
platformUri = "${rootPath}"
scanClassPath = true
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.uml2.codegen.ecore.genmodel.GenModelPackage"
registerGeneratedEPackage = "org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage"
}
component = CooperateXtextGenerator {
configuration = {
project = StandardProjectConfig {
baseName = "${basename}"
rootPath = rootPath
runtimeTest = {
enabled = true
root = "../../tests/${basename}.tests"
}
eclipsePlugin = {
enabled = true
}
eclipsePluginTest = {
enabled = true
root = "../../tests/${basename}.ui.tests"
}
createEclipseMetaData = true
}
code = {
encoding = "UTF-8"
fileHeader = "/*\n * generated by Xtext \${version}\n */"
}
}
language = StandardLanguage {
name = "${basename}.<file extension starting with an upper case character, keep it>"
fileExtensions = "<file extension, keep it>"
referencedResource = "platform:/resource/${basename}.metamodel/model/<name of your genmodel file>.genmodel"
referencedResource = "platform:/resource/${basename}.metamodel/model/<name of your meta model file>.ecore"
referencedResource = "platform:/plugin/org.eclipse.uml2.uml/model/UML.ecore"
referencedResource = "platform:/plugin/org.eclipse.uml2.uml/model/UML.genmodel"
renameRefactoring = fragments.CooperateRenameGeneratorFragment2 auto-inject {}
fragment = ecore2xtext.Ecore2XtextValueConverterServiceFragment2 auto-inject {}
fragment = org.eclipse.xtext.generator.adapter.FragmentAdapter {
fragment = org.eclipse.xtext.generator.formatting2.Formatter2Fragment {}
}
fragment = scoping.ImportNamespacesScopingFragment2 auto-inject {}
fragment = exporting.QualifiedNamesFragment2 auto-inject {}
quickFixProvider = fragments.CooperateQuickfixProviderFragment2 auto-inject {}
generator = {
generateStub = false
}
serializer = {
generateStub = false
}
validator = fragments.CooperateValidatorFragment2 auto-inject {
generateXtendStub = false
}
fragment = junit.Junit4Fragment2 {
generateStub = false
generateXtendStub = false
}
fragment = fragments.CooperateCDOXtextFragment2 auto-inject {}
}
}
}
After editing the MWE2 workflow, you can execute it. This should lead to 4 additional projects. The workflow tries to adjust several files including the plugin.xml
file every time you run the workflow. If the workflow is not able to merge the changes, there will be a plugin.xml_gen
file. If this file exists, you have to merge the changes manually. Otherwise, the changes will not be applied.
After generating the plugins required for the textual editor, you have to adjust some parts of the generated code:
- <basename>.ui plugin - plugin.xml
- Add the matching strategy
de.cooperateproject.modeling.textual.xtext.runtime.ui.editor.CooperateEditorMatchingStrategy
to the editor extension in the extension pointorg.eclipse.ui.editors
- Add the category
de.cooperateproject.ui.preferences.cooperate
to the first page of the page extension in the extension pointorg.eclipse.ui.preferencePages
- Add the term
Diagram
to the name of the first page of the page extension in the extension pointorg.eclipse.ui.preferencePages
- Add the matching strategy
Afer these changes, you can complete your grammar (and meta model). You can always test the editor after executing the MWE2 workflow, starting a new Eclipse instance, and creating an empty file ending with the file extension you specified.
Modeling Environment
Tools