EMF- как программно удалить экземпляр из модели

Я создал свою метамодель под названием WFG.ecore,

С помощью ATL мне удалось преобразовать файл bpmn2 в модель WFG. Преобразование ATL дает объекту WorkFlowэто контейнер всех других объектов в WFG.

Теперь я хотел бы изменить объект WorkFlow программно на яве, но не могу.

Как я могу удалить экземпляр объекта из его контейнера, и так из всех вхождений?

Ниже приведен пример с примерами

            gateways
           +--------->+----------+
           |          |Gateway_1 |
           ♦          +----------+
+-----------+              ^
|WorkFlow_1 |              | nextGateway 0..1
+-----------+              |
           ♦           +---------+
           |           | Node_1  |
           +---------->+---------+
           nodes

Я хотел бы удалить экземпляр Gateway_1так, чтобы он больше не содержался в WorkFlow_1и так что Node_1.getNextGateway->null, Я пытался сделатьWorkFlow_1.getGateways().remove(Gateway_1) но не работает

2 ответа

Наивный ответ заключается в использовании EcoreUtil.delete() или Delete команда. Оба из них удаляют EObject из его контейнера и удалите (то есть обнулите) любые перекрестные ссылки. В целом, однако, вы не хотите делать это таким образом по следующим причинам:

  1. Дочерние ссылки. Хоть EcoreUtil.delete(Gateway_1) удалит Gateway_1 из своего контейнера и из Node_1 ссылка, он не удалит перекрестные ссылки на детей Gateway_1 ДАЖЕ ЧЕРЕЗ ОНИ ТАКЖЕ БУДУТ УДАЛЕНЫ из их контейнера. Таким образом, вы можете получить висячие ссылки на несуществующие объекты, которые были потомками Gateway_1,

  2. Спектакль. Нет надежного способа эффективно найти перекрестные ссылки. Это означает, что каждый EObject в вашей модели будет проверен на наличие перекрестной ссылки на Gateway_1 так что перекрестная ссылка может быть удалена. Что делает EcoreUtil.delete() операция O(n), где n - количество объектов EObject в вашей модели.

Лучшее решение - это сочетание двунаправленных ссылок и карт ссылок. Или Gateway_1 должен знать, кто на него ссылается, или эта информация должна быть доступна в другом месте. Таким образом, вы можете явно удалить все ссылки на Gateway_1 эффективным и полным способом.

Этот ответ близко следует за этим сообщением в блоге, EMF Dos and Don'ts #11 Максимилианом Когелем и Джонасом Хелмингом.

Кстати, EcoreUtil.remove() НЕ выполняет удаление перекрестных ссылок, оно просто удаляет объект EObject из своего контейнера.

DeleteCommand.create(editingDomain, Collections.singleton(Gateway_1));
editingDomain.getCommandStack().execute(command);

И для Узла_1:

Node_1.setNextGateway(null);
Другие вопросы по тегам