Как получить OrderedSet of OccurrenceSpecification от Lifeline в QVTo?
Из диаграммы на странице 570 спецификации UML я пришел к выводу, что 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 ответа
На основании ответа Винсента в сочетании с мнением моего коллеги я придумал следующее решение для 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();
}
Ты прав. Свойство Lifeline::events четко показано на диаграмме и отображается в производных моделях, таких как UML.merged.uml.
К сожалению, Eclipse QVTo использует проекцию Ecore метамодели UML в UML.ecore, где удаляются невидимые противоположности. (Недавнее усовершенствование UML2Ecore позволяет сохранить имя в качестве EAnnotation.) Однако, как только истинное имя свойства "events" было удалено, неявное имя свойства "OccurrenceSpecification" должно работать.
В OCL все ассоциации судоходны в обоих направлениях, поэтому эта потеря является ошибкой. (Новый Eclipse OCL на основе Pivot восходит к основной модели UML, чтобы избежать потерь UML2Ecore. После перехода Eclipse QVTo на Pivot OCL вы должны увидеть ожидаемое поведение.)
Я не знаю, возможно ли это, используя напрямую coveredBy
получить заказанную коллекцию. Как coveredBy
неупорядочен, если вы обращаетесь к нему напрямую с помощью функции, у вас будет непредсказуемый заказ, и если вы попытаетесь получить к нему доступ с помощью eGet(...)
вещи, тот же результат будет происходить.
Однако, если я правильно понял, есть "хитрость", которая может сработать. Он основан на предположении, что каждый OccurrenceSpecification
экземпляр, который вам нужен, удерживается тем же Interaction
который содержит Lifeline
и использует способ, которым EMF хранит содержащиеся элементы. Фактически, каждый содержащийся элемент всегда "упорядочен" относительно своего родителя (и для каждой коллекции, чтобы EMF могла находить элементы обратно, когда ссылки XMI выражаются с использованием позиции элемента в коллекциях). Таким образом, идея заключается в том, чтобы получить доступ ко всем элементам, содержащимся в Interaction
который владеет жизненным путем и фильтрует те, которые содержатся в coveredBy
,
Выражение с Acceleo
Это легко написать в MTL/Acceleo. In знаю, что вы не используете его, но это иллюстрирует, что делает выражение:
# 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()
который определен на EObject
и возвращает EList
который трансформируется в Sequence
(в QVT,eAllContents()
возвращает ETreeIterator
который не трансформируется двигателем QVT).
Итак, как получить доступ к 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
не могут быть доступны, вы все равно можете привести к 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();
}
ограничение
Хорошо, давайте будем честными, это решение, кажется, работает на быстрых тестах, которые я выполнил, но я не уверен на 100%, что у вас будут все необходимые элементы, так как этот код опирается на твердое предположение, что каждый OccurrenceSpecification
ты нужен в том же Interaction
как Liteline
пример. Если вы уверены, что все coveredBy
элементы, которые вам нужны, находятся в Interaction
(Я думаю, что они должны быть), то, это не самое сексуальное решение, но оно должно делать работу.
EDIT>
Решение, предложенное hielsnoppe, более изящно, чем решение, представленное здесь, и должно быть предпочтительным.