如何在QVTo中从生命线获得OrderedSet of OccurrenceSpecifications?

时间:2017-07-18 15:59:07

标签: eclipse uml qvt

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

我拥有的只是coveredBy属性,为我提供(无序)Set(InteractionFragment)。由于我的转换依赖于MessageOcurrenceSpecification的正确顺序,因此我需要自己实现我希望由缺少的events属性实现的内容。

这是我到目前为止所做的:

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

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

显然sortedBy(true)并没有让我走得太远,但我不知道更进一步。谁可以帮忙?

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

3 个答案:

答案 0 :(得分:1)

我不知道是否可以直接使用coveredBy获取有序集合。由于coveredBy是无序的,如果您通过该功能直接访问它,您将有一个不可预测的订单,如果您尝试使用eGet(...)内容访问它,则会出现相同的结果。

但是,如果我理解正确的话,有一个“技巧”可行。 它依赖于以下假设:您需要的每个OccurrenceSpecification实例由包含Interaction的相同Lifeline持有,并使用EMF存储包含元素的方式。实际上,每个包含的元素总是相对于其父元素是“有序的”(对于每个集合,因此当使用集合中的元素位置表示XMI引用时,EMF可以找回元素)。因此,我们的想法是访问拥有生命线的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集合中的元素。

但由于eAllContents(...)不存在,因此在QVT中不那么直观。相反,您必须获得eContents()上定义的EObject的访问权限,并返回EList,该Sequence已转换为eAllContents()(在QVT中,ETreeIterator返回eContents()不是由QVT引擎转换的。{/ p>

那么,如何在帮助程序中访问emf.tools?有两种解决方案:

解决方案1:使用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(); } ...等)。

oclAstype(...)

解决方案2:使用emf.tools

如果由于某种原因无法访问EObject,您仍然可以使用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(); }

OccurrenceSpecification

限制

好吧,让我们说实话,这个解决方案似乎适用于我执行的快速测试,但我不是100%肯定你会拥有你想要的所有元素,因为这段代码依赖于强大的假设,每一个您需要的InteractionLiteline实例位于同一coveredBy。如果您确定所需的所有Interaction元素都在.state('results', { url: '/results', templateUrl: 'html/main_listing.html', redirectTo: 'results.grid' }) //Child state for results state .state('results.grid', { templateUrl: 'html/grid_listing.html' }) //Child state for results state .state('results.list', { templateUrl: 'html/list_listing.html' }) (我认为它们应该是),那么,这不是最性感的解决方案,但它应该完成工作。

<强>编辑&gt;

hielsnoppe提出的solution比我在这里提出的更为优雅,应该是首选。

答案 1 :(得分:1)

根据answer by Vincent结合我的同事的意见,我为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();
}

答案 2 :(得分:0)

你是对的。 Lifeline :: events属性清晰地显示在图表上,并出现在派生模型中,例如UML.merged.uml。

不幸的是,Eclipse QVTo使用UML元模型的Ecore投影到UML.ecore,其中修剪了无法使用的对立面。 (最近的UML2Ecore增强功能允许将名称保存为EAnnotation。)但是,一旦修剪了真实的属性名称“events”,隐式属性名称“OccurrenceSpecification”就应该有效。

所有关联都可以在OCL中双向导航,因此这种丢失是一个错误。 (新的基于Pivot的Eclipse OCL回到主UML模型,以避免UML2Ecore损失。一旦Eclipse QVTo迁移到Pivot OCL,您应该看到您期望的行为。)