2
votes

I have created my metamodel, called WFG.ecore.

With ATL I managed to transform a bpmn2 file in a WFG model. The ATL transformation gives to the object WorkFlow, that is the container of all the other objects in WFG.

Now I would like to modify the object WorkFlow programmatically in Java, but I can not.

How can I delete an object instance from its container, and so from all the occurrences?

Below there is an example with instances

            gateways
           +--------->+----------+
           |          |Gateway_1 |
           ♦          +----------+
+-----------+              ^
|WorkFlow_1 |              | nextGateway 0..1
+-----------+              |
           ♦           +---------+
           |           | Node_1  |
           +---------->+---------+
           nodes

I would like to delete the instance Gateway_1, so that it's no more contained in WorkFlow_1, and so that Node_1.getNextGateway->null. I tried to do WorkFlow_1.getGateways().remove(Gateway_1) but doesn't work

2

2 Answers

1
votes

The naive answer is to use EcoreUtil.delete() or the Delete command. Both of these remove the EObject from its container and remove (i.e. null out) any cross references. In general, though, you don't want to do it that way for the following reasons:

  1. Child references. Though EcoreUtil.delete(Gateway_1) will remove Gateway_1 from its container and from the Node_1 reference, it won't remove any cross references to children of Gateway_1 EVEN THOUGH THEY ALSO WILL BE DELETED from their container. So you could end up with dangling references to nonexistent objects that were children of Gateway_1.

  2. Performance. There's no reliable way to find cross references efficiently. That means that every EObject in your model will be checked to see if it has a cross reference to Gateway_1 so that cross reference can be deleted. That makes EcoreUtil.delete() an O(n) operation where n is the number of EObjects in your model.

The best solution is some combination of bidirectional references and reference maps. Either Gateway_1 should know who is cross referencing it, or that information should be accessible elsewhere. That way you can explicitly remove all references to Gateway_1 in an efficient and complete manner.

This answer closely follows this blog post, EMF Dos and Don'ts #11, by Maximilian Koegel and Jonas Helming.

By the way, EcoreUtil.remove() does NOT do the cross reference removal, it just removes the EObject from its container.

-1
votes
DeleteCommand.create(editingDomain, Collections.singleton(Gateway_1));
editingDomain.getCommandStack().execute(command);

And for Node_1:

Node_1.setNextGateway(null);