Skip to main content
summaryrefslogtreecommitdiffstats
blob: 541196959fe906a329f1f2fcedcbc563c208b144 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/*****************************************************************************
 * Copyright (c) 2010 CEA
 *
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   Atos Origin - Initial API and implementation
 *
 *****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.util;

import java.util.Arrays;
import java.util.List;

import org.eclipse.draw2d.PositionConstants;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.core.commands.DeleteCommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionNodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.emf.type.core.commands.DestroyElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramEditPartsUtil;
import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils;
import org.eclipse.papyrus.infra.services.edit.service.IElementEditService;
import org.eclipse.papyrus.uml.diagram.sequence.RestoreExecutionEndAdvice;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.policies.OLDLifelineXYLayoutEditPolicy;
import org.eclipse.uml2.uml.DestructionOccurrenceSpecification;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.MessageEnd;
import org.eclipse.uml2.uml.OccurrenceSpecification;

/**
 * An Helper to get deleting command for the sequence diagram elements.
 */
public class SequenceDeleteHelper {

	/**
	 * Complete an ICommand which destroys an ExecutionSpecification element to also destroy dependent finish and start events and time/duration
	 * constraint/observation linked with these ends
	 *
	 * @param deleteViewsCmd
	 *            the command to complete
	 * @param editingDomain
	 *            the editing domain
	 * @param executionPart
	 *            the execution specification edit part on which the request is called
	 * @return the deletion command deleteViewsCmd for convenience
	 */
	public static CompoundCommand completeDeleteMessageViewCommand(CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain, EditPart messagePart) {
		if (messagePart instanceof IGraphicalEditPart) {
			EObject obj = ((IGraphicalEditPart) messagePart).resolveSemanticElement();
			if (obj instanceof Message) {
				Message message = (Message) obj;
				LifelineEditPart srcLifelinePart = SequenceUtil.getParentLifelinePart(((ConnectionNodeEditPart) messagePart).getSource());
				MessageEnd send = message.getSendEvent();
				addDeleteRelatedTimePartsToCommand(deleteViewsCmd, editingDomain, srcLifelinePart, send);
				LifelineEditPart tgtLifelinePart = SequenceUtil.getParentLifelinePart(((ConnectionNodeEditPart) messagePart).getTarget());
				MessageEnd receive = message.getReceiveEvent();
				addDeleteRelatedTimePartsToCommand(deleteViewsCmd, editingDomain, tgtLifelinePart, receive);
				// also delete time observation links which are related to message end
			}
		}
		return deleteViewsCmd;
	}

	private static void addDeleteRelatedTimePartsToCommand(CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain, LifelineEditPart lifelineEP, MessageEnd messageEnd) {
		if (lifelineEP != null && messageEnd instanceof OccurrenceSpecification) {
			for (Object lifelineChild : lifelineEP.getChildren()) {
				if (lifelineChild instanceof IBorderItemEditPart) {
					final IBorderItemEditPart timePart = (IBorderItemEditPart) lifelineChild;
					int positionForEvent = SequenceUtil.positionWhereEventIsLinkedToPart((OccurrenceSpecification) messageEnd, timePart);
					if (positionForEvent != PositionConstants.NONE) {
						// time part is linked, delete the view
						Command deleteTimeViewCommand = new ICommandProxy(new DeleteCommand(editingDomain, (View) timePart.getModel()));
						deleteViewsCmd.add(deleteTimeViewCommand);
					}
				}
			}
		}
	}

	/**
	 * Complete an ICommand which destroys an ExecutionSpecification element to also destroy dependent finish and start events and time/duration
	 * constraint/observation linked with these ends
	 *
	 * @param deleteViewsCmd
	 *            the command to complete
	 * @param editingDomain
	 *            the editing domain
	 * @param executionPart
	 *            the execution specification edit part on which the request is called
	 * @return the deletion command deleteViewsCmd for convenience
	 */
	public static CompoundCommand completeDeleteExecutionSpecificationViewCommand(CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain, EditPart executionPart) {
		if (executionPart instanceof IGraphicalEditPart) {
			EObject obj = ((IGraphicalEditPart) executionPart).resolveSemanticElement();
			if (obj instanceof ExecutionSpecification) {
				ExecutionSpecification execution = (ExecutionSpecification) obj;
				LifelineEditPart lifelinePart = SequenceUtil.getParentLifelinePart(executionPart);
				if (lifelinePart != null) {
					for (Object lifelineChild : lifelinePart.getChildren()) {
						if (lifelineChild instanceof IBorderItemEditPart) {
							final IBorderItemEditPart timePart = (IBorderItemEditPart) lifelineChild;
							OccurrenceSpecification start = execution.getStart();
							OccurrenceSpecification finish = execution.getStart();
							int positionForStart = SequenceUtil.positionWhereEventIsLinkedToPart(start, timePart);
							int positionForFinish = SequenceUtil.positionWhereEventIsLinkedToPart(finish, timePart);
							if (positionForStart != PositionConstants.NONE || positionForFinish != PositionConstants.NONE) {
								// time part is linked, delete the view
								Command deleteTimeViewCommand = new ICommandProxy(new DeleteCommand(editingDomain, (View) timePart.getModel()));
								deleteViewsCmd.add(deleteTimeViewCommand);
							}
						}
					}
				}
			}
		}
		return deleteViewsCmd;
	}

	/**
	 * Delete the views associated with a list of elements.
	 *
	 * @param cmd
	 *            the CompositeTransactionalCommand
	 * @param element
	 *            the list of model elements
	 * @param editingDomain
	 *            the editing domain to use.
	 */
	public static void deleteView(CompositeTransactionalCommand cmd, List<Element> elements, TransactionalEditingDomain editingDomain) {
		for (Element element : elements) {
			deleteView(cmd, element, editingDomain);
		}
	}

	/**
	 * Delete the views associated with an element.
	 *
	 * @param cmd
	 *            the CompositeTransactionalCommand
	 * @param element
	 *            the model element referenced by the views
	 * @param editingDomain
	 *            the editing domain to use.
	 */
	public static void deleteView(CompositeTransactionalCommand cmd, Element element, TransactionalEditingDomain editingDomain) {
		// Destroy its views
		@SuppressWarnings("rawtypes")
		List views = DiagramEditPartsUtil.getEObjectViews(element);
		for (Object object : views) {
			if (object instanceof View) {
				cmd.add(new DeleteCommand(editingDomain, (View) object));
			}
		}
	}

	/**
	 * Add complete delete message command
	 *
	 * @param req
	 * @param editPart
	 * @return Command
	 */
	public static Command completeDeleteMessageCommand(DestroyElementRequest req, EditPart editPart) {
		EObject selectedEObject = req.getElementToDestroy();
		IElementEditService provider = ElementEditServiceUtils.getCommandProvider(selectedEObject);
		if (provider != null) {
			// Retrieve delete command from the Element Edit service
			ICommand deleteCommand = provider.getEditCommand(req);
			if (deleteCommand != null) {
				CompoundCommand command = new CompoundCommand(deleteCommand.getLabel());
				command.add(new ICommandProxy(deleteCommand));
				// return completeDeleteMessageCommand(command, (ConnectionEditPart)editPart, req.getEditingDomain());
				destroyMessageEvents(command, Arrays.asList(editPart), req.getEditingDomain());
				return command;
			}
		}
		return UnexecutableCommand.INSTANCE;
	}

	public static void destroyExecutionOccurrenceSpecification(DestroyElementRequest req, CompoundCommand deleteElementsCommand, ShapeNodeEditPart host, ExecutionSpecification es) {
		DestroyElementRequest delStart = new DestroyElementRequest(req.getEditingDomain(), es.getStart(), false);
		deleteElementsCommand.add(new ICommandProxy(new DestroyElementCommand(delStart)));
		DestroyElementRequest delEnd = new DestroyElementRequest(req.getEditingDomain(), es.getFinish(), false);
		deleteElementsCommand.add(new ICommandProxy(new DestroyElementCommand(delEnd)));
		destroyMessageEvents(deleteElementsCommand, host, req.getEditingDomain());
		SequenceDeleteHelper.addDestroyExecutionSpecificationChildrenCommand(deleteElementsCommand, req.getEditingDomain(), host);
	}

	public static void destroyMessageEvents(CompoundCommand deleteElementsCommand, ShapeNodeEditPart host, TransactionalEditingDomain transactionalEditingDomain) {
		destroyMessageEvents(deleteElementsCommand, host.getSourceConnections(), transactionalEditingDomain);
		destroyMessageEvents(deleteElementsCommand, host.getTargetConnections(), transactionalEditingDomain);
	}

	static void destroyMessageEvents(CompoundCommand deleteElementsCommand, List<?> list, TransactionalEditingDomain transactionalEditingDomain) {
		for (Object o : list) {
			if (o instanceof ConnectionEditPart) {
				ConnectionEditPart connectionEP = (ConnectionEditPart) o;
				EObject model = ((ConnectionEditPart) o).resolveSemanticElement();
				if (model instanceof Message) {
					Message message = (Message) model;
					MessageEnd receiveEvent = message.getReceiveEvent();
					MessageEnd sendEvent = message.getSendEvent();
					destroyMessageEvent(deleteElementsCommand, sendEvent, transactionalEditingDomain);
					if (false == receiveEvent instanceof DestructionOccurrenceSpecification) {
						destroyMessageEvent(deleteElementsCommand, receiveEvent, transactionalEditingDomain);
					}
				}
			}
		}
	}

	static void destroyMessageEvent(CompoundCommand deleteElementsCommand, MessageEnd event, TransactionalEditingDomain transactionalEditingDomain) {
		if (event != null) {
			DestroyElementRequest myReq = new DestroyElementRequest(transactionalEditingDomain, event, false);
			// Sometimes, the message end is also the end of a execution.
			RestoreExecutionEndAdvice provider = new RestoreExecutionEndAdvice();
			if (provider != null) {
				ICommand editCommand = provider.getAfterEditCommand(myReq);
				if (editCommand != null && editCommand.canExecute()) {
					deleteElementsCommand.add(new ICommandProxy(editCommand));
				}
			}
			deleteElementsCommand.add(new ICommandProxy(new DestroyElementCommand(myReq)));
		}
	}

	static void addDestroyExecutionSpecificationChildrenCommand(CompoundCommand deleteElementsCommand, TransactionalEditingDomain editingDomain, ShapeNodeEditPart part) {
		List<ShapeNodeEditPart> list = OLDLifelineXYLayoutEditPolicy.getAffixedExecutionSpecificationEditParts(part);
		for (ShapeNodeEditPart p : list) {
			Request request = new EditCommandRequestWrapper(new DestroyElementRequest(p.resolveSemanticElement(), false));
			deleteElementsCommand.add(p.getCommand(request));
			destroyMessageEvents(deleteElementsCommand, p.getSourceConnections(), editingDomain);
			destroyMessageEvents(deleteElementsCommand, p.getTargetConnections(), editingDomain);
		}
	}
}

Back to the top