从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)
并没有让我走得太远,但我不知道更进一步。谁可以帮忙?
到目前为止我所能找到的是其他人多年前在同一个问题上挣扎,但没有解决方案:
答案 0 :(得分:1)
我不知道是否可以直接使用coveredBy
获取有序集合。由于coveredBy
是无序的,如果您通过该功能直接访问它,您将有一个不可预测的订单,如果您尝试使用eGet(...)
内容访问它,则会出现相同的结果。
但是,如果我理解正确的话,有一个“技巧”可行。
它依赖于以下假设:您需要的每个OccurrenceSpecification
实例由包含Interaction
的相同Lifeline
持有,并使用EMF存储包含元素的方式。实际上,每个包含的元素总是相对于其父元素是“有序的”(对于每个集合,因此当使用集合中的元素位置表示XMI引用时,EMF可以找回元素)。因此,我们的想法是访问拥有生命线的Interaction
所包含的所有元素,并过滤coveredBy
中包含的元素。
这很容易用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
?有两种解决方案:
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(...)
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%肯定你会拥有你想要的所有元素,因为这段代码依赖于强大的假设,每一个您需要的Interaction
与Liteline
实例位于同一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,您应该看到您期望的行为。)