【问题标题】:EMF- how to delete programmatically an instance from a modelEMF-如何以编程方式从模型中删除实例
【发布时间】:2014-05-07 08:22:07
【问题描述】:

我创建了我的元模型,名为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) 但不起作用

【问题讨论】:

    标签: eclipse-emf emf eclipse-emf-ecore ecore


    【解决方案1】:

    天真的答案是使用EcoreUtil.delete() 或Delete 命令。这两个都从其容器中删除 EObject 并删除(即清空)任何交叉引用。不过,一般来说,您不想这样做,原因如下:

    1. 子参考。尽管EcoreUtil.delete(Gateway_1) 将从其容器和Node_1 引用中删除Gateway_1,但它不会删除对Gateway_1 子级的任何交叉引用即使它们也将被删除 从他们的容器中。因此,您最终可能会得到对 Gateway_1 的子级不存在对象的悬空引用。

    2. 性能。没有可靠的方法可以有效地找到交叉引用。这意味着将检查模型中的每个 EObject 以查看它是否具有对 Gateway_1 的交叉引用,以便可以删除交叉引用。这使得 EcoreUtil.delete() 成为一个 O(n) 操作,其中 n 是模型中 EObject 的数量。

    最好的解决方案是双向参考和参考地图的某种组合。 Gateway_1 应该知道谁在交叉引用它,或者该信息应该可以在其他地方访问。这样,您就可以高效且完整地明确删除对Gateway_1 的所有引用。

    这个答案紧跟this blog post, EMF Dos and Don'ts #11, by Maximilian Koegel and Jonas Helming。

    顺便说一句,EcoreUtil.remove() 不执行交叉引用删除,它只是从其容器中删除 EObject。

    【讨论】:

    • 从 2.4 版开始,您还有另一个版本 delete(EObject eObject, boolean recursive):“如果递归为真,则在同一资源中包含的对象的子对象同样会从引用它们的任何特征中删除”
    【解决方案2】:
    DeleteCommand.create(editingDomain, Collections.singleton(Gateway_1));
    editingDomain.getCommandStack().execute(command);
    

    对于 Node_1:

    Node_1.setNextGateway(null);
    

    【讨论】:

    • 所以我必须手动删除递归引用,仅仅从容器中删除一个对象是不够的。有没有办法自动做到这一点?手动删除引用很容易出错,特别是如果我以后要添加新的引用,而且很难记住还要添加相关的删除代码。谢谢
    • EcoreUtil 删除方法可以提供帮助:download.eclipse.org/modeling/emf/emf/javadoc/2.5.0/org/eclipse/…
    • DeleteCommand 自动删除交叉引用。你不需要做第二部分,Node_1.setNextGateway(null);
    猜你喜欢
    • 2018-03-23
    • 2010-11-16
    • 2012-04-29
    • 2011-06-18
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    相关资源
    最近更新 更多