Следуйте по связанному списку в OCL
Я использую Bold для Delphi, который имеет реализацию OCL. OCL хорош в фильтрации списков и т. Д. Но я не нашел хорошего общего способа обхода связанных списков.
Предположим, у меня есть класс PlanMission
, Содержит одну ссылку PlanMission.previous
это указывает на себя. Он также имеет логический атрибут isDummy
,
Я хочу просмотреть список PlanMissions
пока у меня нет экземпляра с isDummy
,
я могу сделать
if isdummy then
self
else if previous->notEmpty and previous.isdummy then
previous
else if previous.previous->notEmpty and previous.previous.isdummy then
previous.previous
else
nil
endif
endif
endif
Что я действительно хочу, это что-то вроде этого:
traverseList(previous, isDummy)
traverseList
не существует, но должно иметь 2 параметра.
previous
: Ссылка для подражанияisDummy
: Логическое условие, поэтому я знаю, когда остановиться
Как это можно сделать?
Изменить пояснение Я не хочу никакого кода Delphi. Я хочу код в OCL. Те, кто использует Bold, знают, что я имею в виду. OCL - это язык запросов с объектами запросов, атрибутами и т. Д. Он не содержит побочных эффектов, поэтому он доступен только для чтения. Введение в OCL можно найти здесь.
1 ответ
Вам необходимо вычислить упорядоченное транзитивное замыкание previous
отношения.
(self, self.previous, self.previous.previous и т. д.)
В OCL 2.3.1 это self->asOrderedSet()->closure(previous)
тогда вы можете извлечь первый манекен PlanMission
(или ноль, если его нет):
let c:Set(PlanMission) =
self->asOrderedSet()->closure(previous)->select(x|x.isDummy) in
if c->isEmpty() then null else select(x|x.isDummy)->first()
В разделе 11.9 " Правила отображения предопределенных выражений итераторов" в OCL 2.3.1 приведено определение closure
с точки зрения iterate
что вы можете использовать, если ваш инструмент поддерживает более старую версию OCL.