Следуйте по связанному списку в 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.

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