0

从UML 规范第 570 页的图表中,我得出结论, aLifeline应该具有events属性,持有一个OrderedSet(OcurrenceSpecification). 不幸的是,它不存在,至少在我使用的 QVTo 实现中。

我所拥有的只是coveredBy财产,为我提供 (unordered) Set(InteractionFragment)。由于我的转换依赖于正确的顺序,因此MessageOcurrenceSpecification我需要以某种方式实现我自己期望通过缺失的events属性实现的东西。

这是我到目前为止所拥有的:

helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {

    return self.coveredBy->selectByKind(OccurrenceSpecification)->sortedBy(true);
}

显然sortedBy(true)不会让我走远,但我不知道更多。谁能帮忙?

到目前为止,我所能找到的只是几年前其他人在同样的问题上苦苦挣扎,但没有解决方案:

4

3 回答 3

1

根据文森特的回答以及我同事的意见,我为 QVTo 提出了以下解决方案:

-- -----------------------------------------------------------------------------
-- Polyfill for the missing Lifeline::events property

query Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {

    return self.interaction.fragment
            ->selectByKind(OccurrenceSpecification)
            ->select(os: OccurrenceSpecification | os.covered->includes(self))
            ->asOrderedSet();
}
于 2017-07-19T11:26:11.140 回答
1

不知道有没有可能,直接使用coveredBy获取有序集合。就像coveredBy无序一样,如果您直接通过功能访问它,您将有一个不可预测的顺序,如果您尝试使用这些eGet(...)东西访问它,则会出现相同的结果。

但是,如果我理解正确,有一个“技巧”可以奏效。它依赖于假设OccurrenceSpecification您需要的每个实例都由Interaction包含Lifeline和使用 EMF 存储包含元素的方式的同一实例持有。实际上,每个包含的元素总是相对于其父元素是“有序的”(对于每个集合,EMF 可以在 XMI 引用使用集合中的元素位置表示时找到元素)。因此,我们的想法是访问Interaction拥有生命线的 包含的所有元素并过滤包含在coveredBy.

用 Acceleo 表达

这很容易用 MTL/Acceleo 编写。知道你不使用它,但它说明了表达式的作用:

# In Acceleo:
# 'self' is the lifeline instance
self.interaction.eAllContents(OccurrenceSpecification)->select(e | self.coveredBy->includes(e))->asOrderedSet() 

随着self.interaction我们检索Interaction,然后我们得到所有包含的元素eAllContents(...)并过滤self.coveredBy集合中的元素。

但它在 QVT 中eAllContents(...)不那么直观,因为它不存在。相反,您必须访问eContents()which is defined onEObject并返回EList转换为 a 的 a Sequence(在 QVT 中,eAllContents()返回ETreeIteratorQVT 引擎未转换的 a)。

那么,如何eContents()在助手中获取访问权限呢?有两种解决方案:

解决方案 1:使用emf.tools

emf.tools库使您能够使用asEObject()将对象转换为纯对象的能力,EObject并为您提供更多访问方法(eClass()例如...等)。

import emf.tools;  -- we import the EMF tools library

modeltype UML ...; -- all your metamodel imports and stuffs
...
helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
  return self.interaction.asEObject().eContents()[OccurrenceSpecification]->select(e | self.coveredBy->includes(e))->asOrderedSet();
}

解决方案 2:使用oclAstype(...)

如果由于某种原因emf.tools无法访问,您仍然可以强制转换为EObjectusing oclAsType(...)

modeltype UML ...; -- all your metamodel imports and stuffs
modeltype ECORE "strict" uses ecore('http://www.eclipse.org/emf/2002/Ecore');  -- you also register the Ecore metamodel
...
helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
  return self.interaction.oclAsType(EObject).eContents()[OccurrenceSpecification]->select(e | self.coveredBy->includes(e))->asOrderedSet();
}

局限性

好的,老实说,这个解决方案似乎适用于我执行的快速测试,但我不能 100% 确定你会拥有你想要的所有元素,因为这段代码依赖于OccurrenceSpecification你需要的每个元素的强烈假设InteractionLiteline实例相同。如果您确定coveredBy您需要的所有元素都在Interaction(我认为它们应该是)中,那么这不是最性感的解决方案,但它应该可以工作。

编辑>

hielsnoppe 提出的解决方案比我在这里提出的解决方案更优雅,应该被首选。

于 2017-07-19T10:28:25.467 回答
1

You are correct. The Lifeline::events property is clearly shown on the diagram and appears in derived models such as UML.merged.uml.

Unfortunately Eclipse QVTo uses the Ecore projection of the UML metamodel to UML.ecore where unnavigable opposites are pruned. (A recent UML2Ecore enhancement allows the name to be persisted as an EAnnotation.) However once the true property name "events" has been pruned the implicit property name "OccurrenceSpecification" should work.

All associations are navigable in both directions in OCL, so this loss is a bug. (The new Pivot-based Eclipse OCL goes back to the primary UML model in order to avoid UML2Ecore losses. Once Eclipse QVTo migrates to the Pivot OCL you should see the behavior you expected.)

于 2017-07-25T11:17:05.767 回答