Skip to content

4. Connecting to Domain Models

eckig edited this page Apr 23, 2019 · 1 revision

The tutorial covers how you can connect the visual elements in the graph to some underlying domain model. It requires a basic familiarity with EMF. For an introduction to EMF try here.

This might be necessary in case you wish to "extend" or modify the attributes in the graph model.

As an example we will consider a domain model consisting of Articles (visualised in the graph editor as nodes) and the References between them (visualised as connections).

4.1 Create the EMF model

To create your own domain model you need the Eclipse Modeling Tools.

  • Create new "Ecore Modeling Project"
  • Model the necessary elements for your domain model. If you want to simply follow this tutorial, the following should be enough:

Example EMF model

  • In the "Model Explorer" view expand the *.genmodel file to view your model and open the "Properties" view (usually double-click) -Configure at the very least the "Base Package" and generate the EMF domain model Java code with the leftmost button of the top-right toolbar:

4.2 The EMF editing domain

The two models can be edited within the same EMF editing domain. This helps ensure they remain in sync after undo/redo operations.

First you must get the editing domain instance. There are two possibilities:

  • You created the editing domain yourself. The graph editor will use this editing domain.
  • You didn't create an editing domain. The graph editor will create one and attach it to your model instance when graphEditor.setModel(graphModel) is called.

In the latter case you can get the editing domain instance via:

AdapterFactoryEditingDomain.getEditingDomainFor(graphModel);

The 'articles' model can then be attached to this editing domain as follows:

editingDomain.getResourceSet().getResources().add(articleModel);

4.3 Adding nodes

Suppose you have a button that will add a new 'article' to your editor, which will be represented in the graph by a new node.

Your button handler logic could look something like this:

String id = UUID.randomUUID().toString(); // Create some new ID string here.

GNode node = GraphFactory.eINSTANCE.createGNode();
node.setId(id);
// Set initial node parameters here, e.g. x, y, width, height.

Article article = ArticleFactory.eINSTANCE.createArticle();
article.setId(id);
// Set initial article parameters here, e.g. title, author, description.

EReference nodes = GraphPackage.Literals.GMODEL__NODES;
EReference articles = ArticlePackage.Literals.AMODEL__ARTICLES;

CompoundCommand command = new CompoundCommand();
command.add(AddCommand.create(domain, graphModel, nodes, node));
command.add(AddCommand.create(domain, articleModel, articles, article));

if (command.canExecute())
{
    domain.getCommandStack().execute(command);
}

Note that the GNode and Article objects have been added in the same compound command. If undo is called, both objects will be removed.

It is useful to assign the same ID string to each new object so they can be matched later.

4.4 Adding connections

Connections are a bit different because they can be created & removed internally by the graph editor (e.g. by mouse gesture).

Suppose the user drags one connector to another to create a connection. The following code would ensure that a corresponding Reference is created and added too.

graphEditor.setOnConnectionCreated(connection ->
{
    Reference reference = ArticleFactory.eINSTANCE.createReference();
    // Set initial reference parameters here.

    return AddCommand.create(domain, articleModel, ArticlePackage.Literals.AMODEL__REFERENCES, reference);
});

Again if undo is called, both the connection and reference (here: refs) objects will be removed.