Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: e85d91dee020d9dbebf3e7468dfda98d1e3c6c39 (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
/*****************************************************************************
 * Copyright (c) 2017, 2018 CEA LIST, Christian W. Damus, and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   CEA LIST - Initial API and implementation
 *   Mickaƫl ADAM (ALL4TEC) mickael.adam@all4tec.net - Bug 525369
 *   Christian W. Damus - bug 533679
 *****************************************************************************/

package org.eclipse.papyrus.uml.diagram.sequence.referencialgrilling;

import static org.eclipse.papyrus.uml.diagram.sequence.util.ExecutionSpecificationUtil.getStartedExecution;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gmf.runtime.notation.DecorationNode;
import org.eclipse.papyrus.uml.diagram.sequence.part.UMLDiagramEditorPlugin;
import org.eclipse.papyrus.uml.diagram.sequence.util.LogOptions;
import org.eclipse.papyrus.uml.diagram.sequence.validation.AsyncValidateCommand;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ExecutionOccurrenceSpecification;
import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.Interaction;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.InteractionOperand;
import org.eclipse.uml2.uml.Lifeline;
import org.eclipse.uml2.uml.OccurrenceSpecification;
import org.eclipse.uml2.uml.UMLPackage;

/**
 * This class is a basic class to compute owners.
 *
 * @since 3.0
 */
public class ComputeOwnerHelper implements IComputeOwnerHelper {

	protected static void fillHorizontalMatch(ArrayList<DecorationNode> columns, HashMap<Lifeline, ArrayList<InteractionOperand>> HorizontalLifeLinetoOperand) {
		ArrayList<InteractionOperand> interactionOperandStack = new ArrayList<>();
		for (DecorationNode column : columns) {
			if (column.getElement() instanceof InteractionOperand) {
				if (interactionOperandStack.contains(column.getElement())) {
					UMLDiagramEditorPlugin.log.trace(LogOptions.SEQUENCE_DEBUG_REFERENCEGRID, "update " + ((InteractionOperand) column.getElement()).getName());//$NON-NLS-1$
					interactionOperandStack.remove(column.getElement());
				} else {
					interactionOperandStack.add((InteractionOperand) column.getElement());
				}
			}
			if (column.getElement() instanceof Lifeline) {
				HorizontalLifeLinetoOperand.put((Lifeline) column.getElement(), new ArrayList<>(interactionOperandStack));
			}


		}
	}


	protected static void fillVerticalMatch(ArrayList<DecorationNode> rows, HashMap<Element, ArrayList<InteractionOperand>> verticalElementToOperand) {
		ArrayList<InteractionOperand> interactionOperandStack = new ArrayList<>();
		for (DecorationNode row : rows) {
			if (row.getElement() instanceof InteractionOperand) {
				if (interactionOperandStack.contains(row.getElement())) {
					UMLDiagramEditorPlugin.log.trace(LogOptions.SEQUENCE_DEBUG_REFERENCEGRID, "update " + ((InteractionOperand) row.getElement()).getName());//$NON-NLS-1$
					interactionOperandStack.remove(row.getElement());
				} else {
					interactionOperandStack.add((InteractionOperand) row.getElement());
				}
			} else if (row.getElement() instanceof Element) {
				verticalElementToOperand.put((Element) row.getElement(), new ArrayList<>(interactionOperandStack));
			}
		}

	}

	@Override
	public void updateOwnedByInteractionOperand(EditingDomain domain, ArrayList<DecorationNode> rows, ArrayList<DecorationNode> columns, Interaction interaction, GridManagementEditPolicy grid) {
		// update owner of interaction operand

		HashMap<Lifeline, ArrayList<InteractionOperand>> horizontalLifeLinetoOperand = new HashMap<>();
		HashMap<Element, ArrayList<InteractionOperand>> verticalElementToOperand = new HashMap<>();
		fillHorizontalMatch(columns, horizontalLifeLinetoOperand);
		UMLDiagramEditorPlugin.log.trace(LogOptions.SEQUENCE_DEBUG_REFERENCEGRID, "horizontal parsing done " + horizontalLifeLinetoOperand);//$NON-NLS-1$
		fillVerticalMatch(rows, verticalElementToOperand);
		UMLDiagramEditorPlugin.log.trace(LogOptions.SEQUENCE_DEBUG_REFERENCEGRID, "vertical parsing done " + verticalElementToOperand);//$NON-NLS-1$


		// list of element for the interaction

		ArrayList<InteractionFragment> elementForInteraction = new ArrayList<>();
		// list of element for the interactionOperand
		HashMap<InteractionOperand, ArrayList<InteractionFragment>> elementForInteractionOp = new HashMap<>();
		Iterator<EObject> elementInteraction = interaction.eAllContents();
		while (elementInteraction.hasNext()) {
			Element element = (Element) elementInteraction.next();
			if (element instanceof InteractionFragment) {
				InteractionFragment aFragment = (InteractionFragment) element;
				if (verticalElementToOperand.containsKey(aFragment)) {
					Iterator<Lifeline> iterLifeline = horizontalLifeLinetoOperand.keySet().iterator();
					while (iterLifeline.hasNext()) {
						Lifeline currentLifeline = iterLifeline.next();
						if (currentLifeline.getCoveredBys().contains(aFragment)) {
							ArrayList<InteractionOperand> potentialoperand = intersection(verticalElementToOperand.get(element), horizontalLifeLinetoOperand.get(currentLifeline));
							if (potentialoperand.size() >= 1) {
								simplifyOwnerInteractionOperand(potentialoperand);
								if (potentialoperand.size() == 1) {
									if (elementForInteractionOp.get(potentialoperand.get(0)) == null) {
										elementForInteractionOp.put(potentialoperand.get(0), new ArrayList<InteractionFragment>());
									}
									elementForInteractionOp.get(potentialoperand.get(0)).add(aFragment);
									if (aFragment instanceof OccurrenceSpecification) {
										Optional<ExecutionSpecification> exec = getStartedExecution((OccurrenceSpecification) aFragment);
										exec.ifPresent(elementForInteractionOp.get(potentialoperand.get(0))::add);
									}
								}
							} else {
								if (!(aFragment instanceof InteractionOperand)) {
									elementForInteraction.add(aFragment);
									if (aFragment instanceof ExecutionOccurrenceSpecification) {
										Optional<ExecutionSpecification> exec = getStartedExecution((OccurrenceSpecification) aFragment);
										exec.ifPresent(elementForInteraction::add);
									}
								}
							}
						}
					}
				}


			}

		}

		// update fragments of interaction operrands
		Iterator<InteractionOperand> iterator = elementForInteractionOp.keySet().iterator();
		while (iterator.hasNext()) {
			InteractionOperand interactionOperand = iterator.next();
			ArrayList<InteractionFragment> elements = elementForInteractionOp.get(interactionOperand);
			if (elements.size() != 0) {
				// sort list bu taking
				ArrayList<InteractionFragment> existedFragments = new ArrayList<>();
				ArrayList<InteractionFragment> sorted = sortSemanticFromRows(elements, rows);
				existedFragments.addAll(sorted);
				existedFragments.addAll(interactionOperand.getFragments());
				grid.execute(new SetCommand(domain, interactionOperand, UMLPackage.eINSTANCE.getInteractionOperand_Fragment(), existedFragments));

				AsyncValidateCommand.get(interactionOperand)
						.ifPresent(grid::execute);
			}
		}

		// Update fragments of the interaction
		if (elementForInteraction.size() != 0) {
			ArrayList<InteractionFragment> existedFragments = new ArrayList<>();
			ArrayList<InteractionFragment> sorted = sortSemanticFromRows(elementForInteraction, rows);
			existedFragments.addAll(sorted);
			// Add not sorted element existing into fragment
			for (InteractionFragment interactionFragment : interaction.getFragments()) {
				if (!existedFragments.contains(interactionFragment)) {
					if (interactionFragment instanceof ExecutionSpecification) {
						// if its an execution specification place it after the start
						int indexOfStartOS = existedFragments.indexOf(((ExecutionSpecification) interactionFragment).getStart());
						if (0 <= indexOfStartOS) {
							existedFragments.add(indexOfStartOS + 1, interactionFragment);
						} else {
							existedFragments.add(interactionFragment);
						}
					} else {
						// else add it to the end of the list
						existedFragments.add(interactionFragment);
					}
				}
			}
			grid.execute(new SetCommand(domain, interaction, UMLPackage.eINSTANCE.getInteraction_Fragment(), existedFragments));
		}
	}

	/**
	 * The goal is to create a new list of ordered fragment form a list of fragments by taking general order from rows
	 *
	 * @param fragments
	 *            a list of fragments
	 * @param rows
	 *            the general order of event
	 * @return an ordered list
	 */
	protected ArrayList<InteractionFragment> sortSemanticFromRows(ArrayList<InteractionFragment> fragments, ArrayList<DecorationNode> rows) {
		ArrayList<InteractionFragment> sortedList = new ArrayList<>();
		for (Iterator<DecorationNode> iteratorRow = rows.iterator(); iteratorRow.hasNext();) {
			DecorationNode row = iteratorRow.next();
			if (fragments.contains(row.getElement())) {
				if (!sortedList.contains(row.getElement())) {
					InteractionFragment fragment = (InteractionFragment) row.getElement();
					sortedList.add(fragment);

					if (fragment instanceof OccurrenceSpecification) {
						// These (often) aren't in the rows
						Optional<ExecutionSpecification> execSpec = getStartedExecution((OccurrenceSpecification) fragment);
						execSpec.ifPresent(exec -> {
							if (!sortedList.contains(exec)) {
								sortedList.add(exec);
							}
						});
					}
				}
			}

		}
		return sortedList;
	}

	/**
	 * simplify the list of interaction operand to find only one.
	 * all interaction operand in this list must have a relation owner-owned.
	 *
	 * @param operandList
	 */
	protected static void simplifyOwnerInteractionOperand(ArrayList<InteractionOperand> operandList) {
		/*
		 * while (operandList.size() > 1) {
		 * 
		 * InteractionOperand last = operandList.get(operandList.size() - 1);
		 * EObject parent = last.eContainer();
		 * while (parent != null) {
		 * operandList.remove(parent);
		 * parent = parent.eContainer();
		 * }
		 * }
		 */
	}

	/**
	 * make the intersection of 2 lists
	 *
	 * @param list1
	 * @param list2
	 * @return
	 */
	protected static <T> ArrayList<T> intersection(List<T> list1, List<T> list2) {
		ArrayList<T> list = new ArrayList<>();

		for (T t : list1) {
			if (list2.contains(t)) {
				list.add(t);
			}
		}

		return list;
	}
}

Back to the top