Как получить 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, более изящно, чем решение, представленное здесь, и должно быть предпочтительным.

Другие вопросы по тегам