我已经创建了名为WFG.ecore
的元模型。
使用ATL,我成功地转换了WFG模型中的bpmn2文件。ATL转换提供给对象WorkFlow
,即WFG中所有其他对象的容器。
现在我想用Java编程修改对象WorkFlow
,但我做不到。
如何从对象实例的容器中删除对象实例,以及从所有引用中删除对象?
下面是一个实例的例子
gateways
+--------->+----------+
| |Gateway_1 |
♦ +----------+
+-----------+ ^
|WorkFlow_1 | | nextGateway 0..1
+-----------+ |
♦ +---------+
| | Node_1 |
+---------->+---------+
nodes
我想删除实例Gateway_1
,这样它就不再包含在WorkFlow_1
中,这样Node_1.getNextGateway->null
。我试着去做WorkFlow_1.getGateways().remove(Gateway_1)
但不工作
简单的答案是使用EcoreUtil.delete()
或Delete
命令。这两者都将EObject
从其容器中移除,并移除(即空出(任何交叉引用。不过,总的来说,你不想这样做,原因如下:
-
子引用。尽管
EcoreUtil.delete(Gateway_1)
将从其容器和Node_1
引用中删除Gateway_1
,但它不会删除对Gateway_1
子级的任何交叉引用,即使它们也将从容器中删除。因此,最终可能会出现对Gateway_1
的子对象的不存在对象的悬空引用。 -
性能。没有可靠的方法可以有效地找到交叉引用。这意味着将检查模型中的每个EObject,以查看它是否有对
Gateway_1
的交叉引用,从而可以删除交叉引用。这使得EcoreUtil.delete()
成为O(n(操作,其中n是模型中EObjects的数量。
最好的解决方案是双向引用和引用映射的某种组合。Gateway_1
应该知道谁在交叉引用它,或者该信息应该可以在其他地方访问。通过这种方式,您可以以高效和完整的方式显式地删除对Gateway_1
的所有引用。
这个答案紧跟着Maximilian Koegel和Jonas Helming的这篇博客文章,EMF Dos and Don’ts#11。
顺便说一下,EcoreUtil.remove()
不执行交叉引用删除,它只是从容器中删除EObject。
DeleteCommand.create(editingDomain, Collections.singleton(Gateway_1));
editingDomain.getCommandStack().execute(command);
对于Node_1:
Node_1.setNextGateway(null);