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
из его контейнера и удалите (то есть обнулите) любые перекрестные ссылки. В целом, однако, вы не хотите делать это таким образом по следующим причинам:
Дочерние ссылки. Хоть
EcoreUtil.delete(Gateway_1)
удалитGateway_1
из своего контейнера и изNode_1
ссылка, он не удалит перекрестные ссылки на детейGateway_1
ДАЖЕ ЧЕРЕЗ ОНИ ТАКЖЕ БУДУТ УДАЛЕНЫ из их контейнера. Таким образом, вы можете получить висячие ссылки на несуществующие объекты, которые были потомкамиGateway_1
,Спектакль. Нет надежного способа эффективно найти перекрестные ссылки. Это означает, что каждый 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);