6dd290d2e545e026afd05e1cd35dd6ddc8c62d06
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / uml2sd / core / Frame.java
1 /**********************************************************************
2 * Copyright (c) 2005, 2014 IBM Corporation, Ericsson
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM - Initial API and implementation
10 * Bernd Hufmann - Updated for TMF
11 **********************************************************************/
12
13 package org.eclipse.tracecompass.tmf.ui.views.uml2sd.core;
14
15 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Iterator;
20 import java.util.List;
21
22 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
23 import org.eclipse.tracecompass.tmf.ui.views.uml2sd.drawings.IColor;
24 import org.eclipse.tracecompass.tmf.ui.views.uml2sd.drawings.IGC;
25 import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.SDViewPref;
26 import org.eclipse.tracecompass.tmf.ui.views.uml2sd.util.TimeEventComparator;
27
28 /**
29 * The Frame class is the base sequence diagram graph nodes container.<br>
30 * For instance, only one frame can be drawn in the View.<br>
31 * Lifelines, Messages and Stop which are supposed to represent a Sequence diagram are drawn in a Frame.<br>
32 * Only the graph node added to their representing list will be drawn.
33 *
34 * The lifelines are appended along the X axsis when added in a frame.<br>
35 * The syncMessages are ordered along the Y axsis depending on the event occurrence they are attached to.<br>
36 *
37 * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.Lifeline Lifeline for more event occurence details
38 * @author sveyrier
39 * @version 1.0
40 */
41 public class Frame extends BasicFrame {
42
43 // ------------------------------------------------------------------------
44 // Attributes
45 // ------------------------------------------------------------------------
46 /**
47 * The lifeline that is current highlighted.
48 */
49 private Lifeline fHighlightLifeline = null;
50 /**
51 * The value of the start event.
52 */
53 private int fStartEvent = 0;
54 /**
55 * The number of events in the frame.
56 */
57 private int fNbEvent = 0;
58 /**
59 * The color for highlighting.
60 */
61 private IColor fHighlightColor = null;
62 /**
63 * The list of time events of the corresponding execution occurrences.
64 */
65 private List<SDTimeEvent> fExecutionOccurrencesWithTime;
66 /**
67 * The Array of lifeline categories.
68 */
69 private LifelineCategories[] fLifelineCategories = null;
70
71 // ------------------------------------------------------------------------
72 // Methods
73 // ------------------------------------------------------------------------
74
75 /**
76 * Returns a list of all lifelines known by this frame. Known lifelines are the only one which can be displayed on
77 * screen.
78 *
79 * @return the lifelines list
80 */
81 protected List<GraphNode> getLifelines() {
82 if (!hasChildren()) {
83 return null;
84 }
85 return getNodeMap().get(Lifeline.LIFELINE_TAG);
86 }
87
88 /**
89 * Returns the number of lifelines stored in the frame
90 *
91 * @return the number of lifelines
92 */
93 public int lifeLinesCount() {
94 List<GraphNode> lifelines = getLifelines();
95 if (lifelines != null) {
96 return lifelines.size();
97 }
98 return 0;
99 }
100
101 /**
102 * Returns the lifeline at the given index in the lifelines array
103 *
104 * @param index the position in the lifeline array
105 * @return the lifeline or <code>null</code>
106 */
107 public Lifeline getLifeline(int index) {
108 if ((getLifelines() != null) && (index >= 0) && (index < lifeLinesCount())) {
109 return (Lifeline) getLifelines().get(index);
110 }
111 return null;
112 }
113
114 /**
115 * Returns a list of syncMessages known by this frame. Known syncMessages are the only on which can be displayed on
116 * screen
117 *
118 * @return the syncMessages list
119 */
120 protected List<GraphNode> getSyncMessages() {
121 if (!hasChildren()) {
122 return null;
123 }
124 return getNodeMap().get(SyncMessage.SYNC_MESS_TAG);
125 }
126
127 /**
128 * Returns the number of syncMessages stored in the frame
129 *
130 * @return the number of syncMessage
131 */
132 public int syncMessageCount() {
133 if (getSyncMessages() != null) {
134 return getSyncMessages().size();
135 }
136 return 0;
137 }
138
139 /**
140 * Returns the syncMessage at the given index in the syncMessages array
141 *
142 * @param index the position in the syncMessages array
143 * @return the syncMessage or <code>null</code>
144 */
145 public SyncMessage getSyncMessage(int index) {
146 if ((getSyncMessages() != null) && (index >= 0) && (index < getSyncMessages().size())) {
147 return (SyncMessage) getSyncMessages().get(index);
148 }
149 return null;
150 }
151
152 /**
153 * Returns a list of asyncMessages known by this frame. Known asyncMessages are the only on which can be displayed
154 * on screen
155 *
156 * @return the asyncMessages list or <code>null</code>
157 */
158 protected List<GraphNode> getAsyncMessages() {
159 if (!hasChildren()) {
160 return null;
161 }
162 return getNodeMap().get(AsyncMessage.ASYNC_MESS_TAG);
163 }
164
165 /**
166 * Returns the number of asyncMessage stored in the frame
167 *
168 * @return the number of asyncMessage
169 */
170 public int asyncMessageCount() {
171 if (getAsyncMessages() != null) {
172 return getAsyncMessages().size();
173 }
174 return 0;
175 }
176
177 /**
178 * Returns the asyncMessage at the given index in the asyncMessage array
179 *
180 * @param index the position in the asyncMessage array
181 * @return the asyncMessage or <code>null</code>
182 */
183 public AsyncMessage getAsyncMessage(int index) {
184 if ((getAsyncMessages() != null) && (index >= 0) && (index < getAsyncMessages().size())) {
185 return (AsyncMessage) getAsyncMessages().get(index);
186 }
187 return null;
188 }
189
190 /**
191 * Returns a list of syncMessages return known by this frame. Known syncMessages return are the only on which can be
192 * displayed on screen
193 *
194 * @return the syncMessages return list or <code>null</code>
195 */
196 protected List<GraphNode> getSyncMessagesReturn() {
197 if (!hasChildren()) {
198 return null;
199 }
200 return getNodeMap().get(SyncMessageReturn.SYNC_MESS_RET_TAG);
201 }
202
203 /**
204 * Returns the number of syncMessageReturn stored in the frame
205 *
206 * @return the number of syncMessageReturn
207 */
208 public int syncMessageReturnCount() {
209 if (getSyncMessagesReturn() != null) {
210 return getSyncMessagesReturn().size();
211 }
212 return 0;
213 }
214
215 /**
216 * Returns the syncMessageReturn at the given index in the syncMessageReturn array
217 *
218 * @param index the position in the syncMessageReturn array
219 * @return the syncMessageReturn or <code>null</code>
220 */
221 public SyncMessageReturn getSyncMessageReturn(int index) {
222 if ((getSyncMessagesReturn() != null) && (index >= 0) && (index < getSyncMessagesReturn().size())) {
223 return (SyncMessageReturn) getSyncMessagesReturn().get(index);
224 }
225 return null;
226 }
227
228 /**
229 * Returns a list of asyncMessageRetun known by this frame. Known asyncMessageRetun are the only on which can be
230 * displayed on screen
231 *
232 * @return the asyncMessageRetun list or <code>null</code>
233 */
234 protected List<GraphNode> getAsyncMessagesReturn() {
235 if (!hasChildren()) {
236 return null;
237 }
238 return getNodeMap().get(AsyncMessageReturn.ASYNC_MESS_RET_TAG);
239 }
240
241 /**
242 * Returns the number of asyncMessageReturn stored in the frame
243 *
244 * @return the number of asyncMessageReturn
245 */
246 public int asyncMessageReturnCount() {
247 if (getAsyncMessagesReturn() != null) {
248 return getAsyncMessagesReturn().size();
249 }
250 return 0;
251 }
252
253 /**
254 * Returns the asyncMessageReturn at the given index in the asyncMessageReturn array
255 *
256 * @param index the position in the asyncMessageReturn array
257 * @return the asyncMessageReturn or <code>null</code>
258 */
259 public AsyncMessageReturn getAsyncMessageReturn(int index) {
260 if ((getAsyncMessagesReturn() != null) && (index >= 0) && (index < getAsyncMessagesReturn().size())) {
261 return (AsyncMessageReturn) getAsyncMessagesReturn().get(index);
262 }
263 return null;
264 }
265
266 /**
267 * Adds a lifeline to the frame lifelines list. The lifeline X drawing order depends on the lifeline addition order
268 * into the frame lifelines list.
269 *
270 * @param lifeline the lifeline to add
271 */
272 public void addLifeLine(Lifeline lifeline) {
273 setComputeMinMax(true);
274 if (lifeline == null) {
275 return;
276 }
277 // set the lifeline parent frame
278 lifeline.setFrame(this);
279 // Increate the frame lifeline counter
280 // and set the lifeline drawing order
281 lifeline.setIndex(getNewHorizontalIndex());
282 if (lifeline.hasTimeInfo()) {
283 setHasTimeInfo(true);
284 }
285 // add the lifeline to the lifelines list
286 addNode(lifeline);
287 }
288
289 /**
290 * Returns the first visible lifeline drawn in the view
291 *
292 * @return the first visible lifeline index
293 */
294 public int getFirstVisibleLifeline() {
295 if (!hasChildren()) {
296 return 0;
297 }
298 Integer ret = getIndexes().get(Lifeline.LIFELINE_TAG);
299 return (ret == null ? 0 : ret.intValue());
300 }
301
302 /**
303 * Returns the first visible synchronous message drawn in the view
304 *
305 * @return the first visible synchronous message index
306 */
307 public int getFirstVisibleSyncMessage() {
308 if (!hasChildren()) {
309 return 0;
310 }
311 Integer ret = getIndexes().get(SyncMessage.SYNC_MESS_TAG);
312 return (ret == null ? 0 : ret.intValue());
313 }
314
315 /**
316 * Returns the first visible synchronous message return drawn in the view
317 *
318 * @return the first visible synchronous message return index
319 */
320 public int getFirstVisibleSyncMessageReturn() {
321 if (!hasChildren()) {
322 return 0;
323 }
324 Integer ret = getIndexes().get(SyncMessageReturn.SYNC_MESS_RET_TAG);
325 return (ret == null ? 0 : ret.intValue());
326 }
327
328 /**
329 * Returns the first visible synchronous message drawn in the view
330 *
331 * @return the first visible synchronous message index
332 */
333 public int getFirstVisibleAsyncMessage() {
334 if (!hasChildren()) {
335 return 0;
336 }
337 Integer ret = getIndexes().get(AsyncMessage.ASYNC_MESS_TAG);
338 return (ret == null ? 0 : ret.intValue());
339 }
340
341 /**
342 * Returns the first visible synchronous message return drawn in the view
343 *
344 * @return the first visible synchronous message return index
345 */
346 public int getFirstVisibleAsyncMessageReturn() {
347 if (!hasChildren()) {
348 return 0;
349 }
350 Integer ret = getIndexes().get(AsyncMessageReturn.ASYNC_MESS_RET_TAG);
351 return (ret == null ? 0 : ret.intValue());
352 }
353
354 /**
355 * Returns the list of execution occurrences.
356 *
357 * @return the list of execution occurrences
358 */
359 public List<SDTimeEvent> getExecutionOccurrencesWithTime() {
360 return fExecutionOccurrencesWithTime;
361 }
362
363 /**
364 * Inserts a lifeline after a given lifeline.
365 *
366 * @param toInsert A lifeline to insert
367 * @param after A lifelife the toInsert-lifeline will be inserted after.
368 */
369 public void insertLifelineAfter(Lifeline toInsert, Lifeline after) {
370 if ((toInsert == null)) {
371 return;
372 }
373 if (toInsert == after) {
374 return;
375 }
376 int insertPoint = 0;
377 if (after != null) {
378 insertPoint = after.getIndex();
379 }
380 int removePoint = toInsert.getIndex() - 1;
381 if (removePoint >= insertPoint) {
382 getLifelines().remove(removePoint);
383 }
384 getLifelines().add(insertPoint, toInsert);
385 if (removePoint < insertPoint) {
386 getLifelines().remove(removePoint);
387 }
388
389 if (removePoint >= insertPoint) {
390 toInsert.setIndex(insertPoint + 1);
391 } else {
392 toInsert.setIndex(insertPoint - 1);
393 }
394
395 insertPoint++;
396 if (removePoint >= insertPoint) {
397 for (int i = insertPoint; i < getLifelines().size(); i++) {
398 getLifeline(i).setIndex(i + 1);
399 }
400 } else {
401 for (int i = 0; i < insertPoint && i < getLifelines().size(); i++) {
402 getLifeline(i).setIndex(i + 1);
403 }
404 }
405 }
406
407 /**
408 * Inserts a lifeline before a given lifeline.
409 *
410 * @param toInsert
411 * A lifeline to insert
412 * @param before
413 * A lifeline the toInsert-lifeline will be inserted before.
414 */
415 public void insertLifelineBefore(Lifeline toInsert, Lifeline before) {
416 if ((toInsert == null)) {
417 return;
418 }
419 if (toInsert == before) {
420 return;
421 }
422 int insertPoint = 0;
423 if (before != null) {
424 insertPoint = before.getIndex() - 1;
425 }
426 int removePoint = toInsert.getIndex() - 1;
427 if (removePoint >= insertPoint) {
428 getLifelines().remove(removePoint);
429 }
430 getLifelines().add(insertPoint, toInsert);
431 if (removePoint < insertPoint) {
432 getLifelines().remove(removePoint);
433 }
434
435 if (removePoint >= insertPoint) {
436 toInsert.setIndex(insertPoint + 1);
437 } else {
438 toInsert.setIndex(insertPoint - 1);
439 }
440
441 insertPoint++;
442 if (removePoint >= insertPoint) {
443 for (int i = insertPoint; i < getLifelines().size(); i++) {
444 getLifeline(i).setIndex(i + 1);
445 }
446 } else {
447 for (int i = 0; i < insertPoint && i < getLifelines().size(); i++) {
448 getLifeline(i).setIndex(i + 1);
449 }
450 }
451 }
452
453 /**
454 * Gets the closer life line to the given x-coordinate.
455 *
456 * @param x A x coordinate
457 * @return the closer lifeline
458 */
459 public Lifeline getCloserLifeline(int x) {
460 int index = (x - Metrics.FRAME_H_MARGIN + Metrics.LIFELINE_H_MAGIN) / Metrics.swimmingLaneWidth() - 1;
461 if (index < 0) {
462 index = 0;
463 }
464 if (index >= getLifelines().size()) {
465 index = getLifelines().size() - 1;
466 }
467 Lifeline node1, node2, node3;
468 int dist1, dist2, dist3;
469 node1 = node2 = node3 = getLifeline(index);
470 dist1 = dist2 = dist3 = Math.abs(node1.getX() + node1.getWidth() / 2 - x);
471 if (index > 0) {
472 node2 = getLifeline(index - 1);
473 dist2 = Math.abs(node2.getX() + node2.getWidth() / 2 - x);
474 }
475 if (index < getLifelines().size() - 1) {
476 node3 = getLifeline(index + 1);
477 dist3 = Math.abs(node3.getX() + node3.getWidth() / 2 - x);
478 }
479 if (dist1 <= dist2 && dist1 <= dist3) {
480 return node1;
481 } else if (dist2 <= dist1 && dist2 <= dist3) {
482 return node2;
483 }
484 return node3;
485 }
486
487 /**
488 * Re-orders the given list of lifelines.
489 *
490 * @param list A list of lifelines to reorder.
491 */
492 public void reorder(List<?> list) {
493 for (int i = 0; i < list.size(); i++) {
494 if (list.get(i) instanceof Lifeline[]) {
495 Lifeline temp[] = (Lifeline[]) list.get(i);
496 if (temp.length == 2) {
497 if (temp[1] == null) {
498 insertLifelineAfter(temp[0], getLifeline(lifeLinesCount() - 1));
499 } else {
500 insertLifelineBefore(temp[0], temp[1]);
501 }
502 }
503 }
504 }
505 }
506
507 /**
508 * Resets the time compression information.
509 */
510 public void resetTimeCompression() {
511 fHighlightLifeline = null;
512 this.fStartEvent = 0;
513 this.fNbEvent = 0;
514 fHighlightColor = null;
515 }
516
517 @Override
518 protected void computeMinMax() {
519 List<SDTimeEvent> timeArray = buildTimeArray();
520 if ((timeArray == null) || timeArray.isEmpty()) {
521 return;
522 }
523 for (int i = 0; i < timeArray.size() - 1; i++) {
524 SDTimeEvent m1 = timeArray.get(i);
525 SDTimeEvent m2 = timeArray.get(i + 1);
526 if (SDViewPref.getInstance().excludeExternalTime() && ((m1.getGraphNode() instanceof BaseMessage) && (m2.getGraphNode() instanceof BaseMessage))) {
527 BaseMessage mes1 = (BaseMessage) m1.getGraphNode();
528 BaseMessage mes2 = (BaseMessage) m2.getGraphNode();
529 if ((mes2.getStartLifeline() == null) || (mes1.getEndLifeline() == null)) {
530 continue;
531 }
532 }
533
534 updateMinMax(m1, m2);
535 }
536 }
537
538 /**
539 * Find the two graph nodes that are closest to this date, one just earlier, second just later. If date is before
540 * any graph node, bounds[0] is null and bounds[1] is the earliest. If date is after any graph node, bounds[1] is
541 * null and bounds[0] is the latest.
542 *
543 * @param dateToFind date to be found
544 * @param bounds a two items array that will receive bounds if found
545 * @return true if both bounds not null
546 */
547 public boolean findDateBounds(ITmfTimestamp dateToFind, ITimeRange bounds[]) {
548 if (hasTimeInfo()) {
549 List<SDTimeEvent> timeArray = buildTimeArray();
550
551 if ((timeArray == null) || timeArray.isEmpty()) {
552 return false;
553 }
554
555 bounds[0] = null;
556 bounds[1] = null;
557 for (int i = 0; i < timeArray.size(); i++) {
558 SDTimeEvent m = timeArray.get(i);
559 if (m.getTime().compareTo(dateToFind) > 0) {
560 bounds[1] = m.getGraphNode();
561 if (i > 0) {
562 bounds[0] = timeArray.get(i - 1).getGraphNode();
563 return true;
564 }
565 return false;
566 }
567 }
568 bounds[0] = timeArray.get(timeArray.size() - 1).getGraphNode();
569 }
570 return false;
571 }
572
573 /**
574 * Highlights the time compression.
575 *
576 * @param lifeline A lifeline to highlight
577 * @param startEvent A start event number
578 * @param nbEvent A number of events
579 * @param color A color for highlighting
580 */
581 public void highlightTimeCompression(Lifeline lifeline, int startEvent, int nbEvent, IColor color) {
582 fHighlightLifeline = lifeline;
583 this.fStartEvent = startEvent;
584 this.fNbEvent = nbEvent;
585 fHighlightColor = color;
586 }
587
588 /**
589 * Set the lifeline categories which will be use during the lifelines creation
590 *
591 * @see Lifeline#setCategory(int)
592 * @param categories the lifeline categories array
593 */
594 public void setLifelineCategories(LifelineCategories[] categories) {
595 fLifelineCategories = Arrays.copyOf(categories, categories.length);
596 }
597
598 /**
599 * Returns the lifeline categories array set for the this frame
600 *
601 * @return the lifeline categories array or null if not set
602 */
603 public LifelineCategories[] getLifelineCategories() {
604 return Arrays.copyOf(fLifelineCategories, fLifelineCategories.length);
605 }
606
607 /**
608 * Adds a message to the Frame message list. Four kinds of syncMessages can be added:<br>
609 * - synchronous syncMessages<br>
610 * - synchronous syncMessages return<br>
611 * - asynchronous syncMessages<br>
612 * - asynchronous syncMessages return<br>
613 * For drawing performance reason, it is recommended to add synchronous syncMessages in the same order they should
614 * appear along the Y axis in the Frame.
615 *
616 * @param message the message to add
617 */
618 public void addMessage(BaseMessage message) {
619 addNode(message);
620 }
621
622 @Override
623 public void draw(IGC context) {
624 drawFrame(context);
625 if (!hasChildren()) {
626 return;
627 }
628
629 if (fHighlightLifeline != null) {
630 IColor backupColor = context.getBackground();
631 context.setBackground(SDViewPref.getInstance().getTimeCompressionSelectionColor());
632 int gy = fHighlightLifeline.getY() + fHighlightLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * fStartEvent;
633 context.fillRectangle(Metrics.FRAME_H_MARGIN + 1, gy, fHighlightLifeline.getX() + Metrics.getLifelineWidth() / 2 - Metrics.FRAME_H_MARGIN, (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * fNbEvent);
634 context.setBackground(backupColor);
635 }
636 super.draw(context, false);
637 int lifelineArryStep = 1;
638 if (Metrics.swimmingLaneWidth() * context.getZoom() < Metrics.LIFELINE_SIGNIFICANT_HSPACING) {
639 lifelineArryStep = Math.round(Metrics.LIFELINE_SIGNIFICANT_HSPACING / (Metrics.swimmingLaneWidth() * context.getZoom()));
640 }
641 if (getIndexes().size() == 0) {
642 return;
643 }
644 int lifeLineDrawIndex = checkNotNull(getIndexes().get(Lifeline.LIFELINE_TAG)).intValue();
645 List<GraphNode> nodeList = checkNotNull(getNodeMap().get(Lifeline.LIFELINE_TAG));
646 for (int i = lifeLineDrawIndex; i < nodeList.size(); i = i + lifelineArryStep) {
647 Lifeline toDraw = (Lifeline) nodeList.get(i);
648 if (toDraw.getX() - Metrics.LIFELINE_SPACING / 2 > context.getContentsX() + context.getVisibleWidth()) {
649 break;
650 }
651 toDraw.drawName(context);
652
653 if (fHighlightLifeline != null) {
654 if (toDraw == fHighlightLifeline) {
655 toDraw.highlightExecOccurrenceRegion(context, fStartEvent, fNbEvent, fHighlightColor);
656 } else if (toDraw.getIndex() < fHighlightLifeline.getIndex()) {
657 int acIndex = toDraw.getExecOccurrenceDrawIndex();
658 // acIndex = first visible execution occurrence
659 // for drawing speed reason with only search on the visible subset
660 if (toDraw.getExecutions() != null) {
661 for (int index = acIndex; index < toDraw.getExecutions().size(); index++) {
662 BasicExecutionOccurrence exec = (BasicExecutionOccurrence) toDraw.getExecutions().get(index);
663 int tempEvent = fStartEvent;
664 for (int j = 0; j < fNbEvent; j++) {
665 if (((tempEvent >= exec.getStartOccurrence()) && (tempEvent <= exec.getEndOccurrence()) && (tempEvent + 1 >= exec.getStartOccurrence()) && (tempEvent + 1 <= exec.getEndOccurrence()))) {
666 toDraw.highlightExecOccurrenceRegion(context, tempEvent, 1, SDViewPref.getInstance().getTimeCompressionSelectionColor());
667 }
668 tempEvent = tempEvent + 1;
669 }
670 // if we are outside the visible area we stop right now
671 // This works because execution occurrences are ordered along the Y axis
672 if (exec.getY() > getY()) {
673 break;
674 }
675 }
676 }
677 }
678 }
679 }
680 }
681
682 @Override
683 protected List<SDTimeEvent> buildTimeArray() {
684
685 if (!hasChildren()) {
686 return new ArrayList<>();
687 }
688
689 List<SDTimeEvent> timeArray = super.buildTimeArray();
690 fExecutionOccurrencesWithTime = null;
691 if (getLifelines() != null) {
692 List<GraphNode> nodeList = checkNotNull(getNodeMap().get(Lifeline.LIFELINE_TAG));
693 for (int i = 0; i < nodeList.size(); i++) {
694 Lifeline lifeline = (Lifeline) nodeList.get(i);
695 if (lifeline.hasTimeInfo() && lifeline.getExecutions() != null) {
696 for (Iterator<GraphNode> j = lifeline.getExecutions().iterator(); j.hasNext();) {
697 GraphNode o = j.next();
698 if (o instanceof ExecutionOccurrence) {
699 ExecutionOccurrence eo = (ExecutionOccurrence) o;
700 if (eo.hasTimeInfo()) {
701 int event = eo.getStartOccurrence();
702 ITmfTimestamp time = eo.getStartTime();
703 SDTimeEvent f = new SDTimeEvent(time, event, eo);
704 timeArray.add(f);
705 if (fExecutionOccurrencesWithTime == null) {
706 fExecutionOccurrencesWithTime = new ArrayList<>();
707 }
708 fExecutionOccurrencesWithTime.add(f);
709 event = eo.getEndOccurrence();
710 time = eo.getEndTime();
711 f = new SDTimeEvent(time, event, eo);
712 timeArray.add(f);
713 fExecutionOccurrencesWithTime.add(f);
714 }
715 }
716 }
717 }
718 }
719 }
720
721 if (fExecutionOccurrencesWithTime != null) {
722 SDTimeEvent[] temp = fExecutionOccurrencesWithTime.toArray(new SDTimeEvent[fExecutionOccurrencesWithTime.size()]);
723 Arrays.sort(temp, new TimeEventComparator());
724 fExecutionOccurrencesWithTime = Arrays.asList(temp);
725 }
726 SDTimeEvent[] temp = timeArray.toArray(new SDTimeEvent[timeArray.size()]);
727 Arrays.sort(temp, new TimeEventComparator());
728 timeArray = Arrays.asList(temp);
729 return timeArray;
730 }
731
732 /**
733 * Get the closer leaving message.
734 *
735 * @param lifeline A lifeline reference
736 * @param message A message reference
737 * @param list A list of graph nodes
738 * @param smallerEvent A smaller event flag
739 * @return the closer leaving message.
740 */
741 protected GraphNode getCloserLeavingMessage(Lifeline lifeline, BaseMessage message, List<GraphNode> list, boolean smallerEvent) {
742 if (list == null) {
743 return null;
744 }
745
746 if (!smallerEvent) {
747 int event = 0;
748 if (message != null) {
749 event = message.getEventOccurrence();
750 }
751 for (int i = 0; i < list.size(); i++) {
752 GraphNode node = list.get(i);
753 if (node instanceof SyncMessage) {
754 SyncMessage syncNode = (SyncMessage) node;
755 if ((syncNode.getEventOccurrence() > event) && (syncNode.getStartLifeline() == lifeline) && !syncNode.isSameAs(message)) {
756 return node;
757 }
758 } else if (node instanceof AsyncMessage) {
759 AsyncMessage asyncNode = (AsyncMessage) node;
760 if ((asyncNode.getStartOccurrence() > event) && (asyncNode.getStartLifeline() == lifeline) && !asyncNode.isSameAs(message)) {
761 return node;
762 }
763 }
764 }
765 } else {
766 int event = getMaxEventOccurrence();
767 if (message != null) {
768 if (message instanceof AsyncMessage) {
769 event = ((AsyncMessage) message).getStartOccurrence();
770 } else {
771 event = message.getEventOccurrence();
772 }
773 }
774 for (int i = list.size() - 1; i >= 0; i--) {
775 GraphNode node = list.get(i);
776 if (node instanceof SyncMessage) {
777 SyncMessage syncNode = (SyncMessage) node;
778 if ((syncNode.getEventOccurrence() < event) && (syncNode.getStartLifeline() == lifeline) && !syncNode.isSameAs(message)) {
779 return node;
780 }
781 } else if (node instanceof AsyncMessage) {
782 AsyncMessage asyncNode = (AsyncMessage) node;
783 if ((asyncNode.getStartOccurrence() < event) && (asyncNode.getStartLifeline() == lifeline) && !asyncNode.isSameAs(message)) {
784 return node;
785 }
786 }
787 }
788 }
789 return null;
790 }
791
792
793 /**
794 * Get the closer entering message.
795 *
796 * @param lifeline A lifeline reference
797 * @param message A message reference
798 * @param list A list of graph nodes
799 * @param smallerEvent A smaller event flag
800 * @return the closer entering message.
801 */
802 protected GraphNode getCloserEnteringMessage(Lifeline lifeline, BaseMessage message, List<GraphNode> list, boolean smallerEvent) {
803 if (list == null) {
804 return null;
805 }
806 if (!smallerEvent) {
807 int event = 0;
808 if (message != null) {
809 event = message.getEventOccurrence();
810 }
811 for (int i = 0; i < list.size(); i++) {
812 GraphNode node = list.get(i);
813 if (node instanceof SyncMessage) {
814 SyncMessage syncNode = (SyncMessage) node;
815 if ((syncNode.getEventOccurrence() > event) && (syncNode.getEndLifeline() == lifeline) && !syncNode.isSameAs(message)) {
816 return node;
817 }
818 } else if (node instanceof AsyncMessage) {
819 AsyncMessage asyncNode = (AsyncMessage) node;
820 if ((asyncNode.getStartOccurrence() > event) && (asyncNode.getEndLifeline() == lifeline) && !asyncNode.isSameAs(message)) {
821 return node;
822 }
823 }
824 }
825 } else {
826 int event = getMaxEventOccurrence();
827 if (message != null) {
828 if (message instanceof AsyncMessage) {
829 event = ((AsyncMessage) message).getStartOccurrence();
830 } else {
831 event = message.getEventOccurrence();
832 }
833 }
834 for (int i = list.size() - 1; i >= 0; i--) {
835 GraphNode node = list.get(i);
836 if (node instanceof SyncMessage) {
837 SyncMessage syncNode = (SyncMessage) node;
838 if ((syncNode.getEventOccurrence() < event) && (syncNode.getEndLifeline() == lifeline) && !syncNode.isSameAs(message)) {
839 return node;
840 }
841 } else if (node instanceof AsyncMessage) {
842 AsyncMessage asyncNode = (AsyncMessage) node;
843 if ((asyncNode.getStartOccurrence() < event) && (asyncNode.getEndLifeline() == lifeline) && !asyncNode.isSameAs(message)) {
844 return node;
845 }
846 }
847 }
848 }
849 return null;
850 }
851
852 /**
853 * Get distance of given event from given graph node.
854 *
855 * @param node A graph node reference.
856 * @param event A event number to check.
857 * @return distance of event from graph node.
858 */
859 protected int distanceFromEvent(GraphNode node, int event) {
860 int distance = 0;
861 if (node instanceof SyncMessage) {
862 distance = ((SyncMessage) node).getEventOccurrence() - event;
863 } else if (node instanceof AsyncMessage) {
864 int start = ((AsyncMessage) node).getStartOccurrence();
865 int end = ((AsyncMessage) node).getEndOccurrence();
866 if ((start - event) < (end - event)) {
867 distance = start - event;
868 } else {
869 distance = end - event;
870 }
871 }
872 return Math.abs(distance);
873 }
874
875 /**
876 * Get node from 2 given nodes that is close to event.
877 *
878 * @param node1 A first graph node
879 * @param node2 A second graph node
880 * @param event A event to check.
881 * @return graph node that is closer or <code>null</code>
882 */
883 protected GraphNode getCloserToEvent(GraphNode node1, GraphNode node2, int event) {
884 if ((node1 != null) && (node2 != null)) {
885 if (distanceFromEvent(node1, event) < distanceFromEvent(node2, event)) {
886 return node1;
887 }
888 return node2;
889 } else if (node1 != null) {
890 return node1;
891 } else if (node2 != null) {
892 return node2;
893 }
894 return null;
895 }
896
897 /**
898 * Get called message based on given start message.
899 *
900 * @param startMessage A start message to check.
901 * @return called message (graph node) or <code>null</code>
902 */
903 public GraphNode getCalledMessage(BaseMessage startMessage) {
904 int event = 0;
905 GraphNode result = null;
906 Lifeline lifeline = null;
907 if (startMessage != null) {
908 event = startMessage.getEventOccurrence();
909 lifeline = startMessage.getEndLifeline();
910 if (lifeline == null) {
911 lifeline = startMessage.getStartLifeline();
912 }
913 }
914 if (lifeline == null) {
915 return null;
916 }
917 GraphNode message = getCloserLeavingMessage(lifeline, startMessage, getSyncMessages(), false);
918 GraphNode messageReturn = getCloserLeavingMessage(lifeline, startMessage, getSyncMessagesReturn(), false);
919 result = getCloserToEvent(message, messageReturn, event);
920 message = getCloserLeavingMessage(lifeline, startMessage, getAsyncMessages(), false);
921 result = getCloserToEvent(result, message, event);
922 messageReturn = getCloserLeavingMessage(lifeline, startMessage, getAsyncMessagesReturn(), false);
923 result = getCloserToEvent(result, messageReturn, event);
924 return result;
925 }
926
927 /**
928 * Get caller message based on given start message.
929 *
930 * @param startMessage A start message to check.
931 * @return called message (graph node) or <code>null</code>
932 */
933 public GraphNode getCallerMessage(BaseMessage startMessage) {
934 int event = getMaxEventOccurrence();
935 GraphNode result = null;
936 Lifeline lifeline = null;
937 if (startMessage != null) {
938 event = startMessage.getEventOccurrence();
939 lifeline = startMessage.getStartLifeline();
940 if (lifeline == null) {
941 lifeline = startMessage.getEndLifeline();
942 }
943 }
944 if (lifeline == null) {
945 return null;
946 }
947 GraphNode message = getCloserEnteringMessage(lifeline, startMessage, getSyncMessages(), true);
948 GraphNode messageReturn = getCloserEnteringMessage(lifeline, startMessage, getSyncMessagesReturn(), true);
949 result = getCloserToEvent(message, messageReturn, event);
950 message = getCloserEnteringMessage(lifeline, startMessage, getAsyncMessages(), true);
951 result = getCloserToEvent(result, message, event);
952 messageReturn = getCloserEnteringMessage(lifeline, startMessage, getAsyncMessagesReturn(), true);
953 result = getCloserToEvent(result, messageReturn, event);
954 return result;
955 }
956
957 /**
958 * Get next lifeline based on given message.
959 *
960 * @param lifeline A lifeline reference
961 * @param startMessage A start message to check
962 * @return next lifeline or <code>null</code>
963 */
964 public GraphNode getNextLifelineMessage(Lifeline lifeline, BaseMessage startMessage) {
965 int event = 0;
966 if (startMessage != null) {
967 event = startMessage.getEventOccurrence();
968 }
969 if (lifeline == null) {
970 return null;
971 }
972 GraphNode message = getCloserLeavingMessage(lifeline, startMessage, getSyncMessages(), false);
973 GraphNode messageReturn = getCloserLeavingMessage(lifeline, startMessage, getSyncMessagesReturn(), false);
974 GraphNode result = getCloserToEvent(message, messageReturn, event);
975 message = getCloserLeavingMessage(lifeline, startMessage, getAsyncMessages(), false);
976 result = getCloserToEvent(result, message, event);
977 messageReturn = getCloserLeavingMessage(lifeline, startMessage, getAsyncMessagesReturn(), false);
978 result = getCloserToEvent(result, messageReturn, event);
979 return result;
980 }
981
982 /**
983 * Get previous lifeline based on given message.
984 *
985 * @param lifeline A lifeline reference
986 * @param startMessage A start message to check.
987 * @return previous lifeline or <code>null</code>
988 */
989 public GraphNode getPrevLifelineMessage(Lifeline lifeline, BaseMessage startMessage) {
990 int event = getMaxEventOccurrence();
991 if (startMessage != null) {
992 if (startMessage instanceof AsyncMessage) {
993 event = ((AsyncMessage) startMessage).getStartOccurrence();
994 } else {
995 event = startMessage.getEventOccurrence();
996 }
997 }
998 if (lifeline == null) {
999 return null;
1000 }
1001 GraphNode message = getCloserLeavingMessage(lifeline, startMessage, getSyncMessages(), true);
1002 GraphNode messageReturn = getCloserLeavingMessage(lifeline, startMessage, getSyncMessagesReturn(), true);
1003 GraphNode result = getCloserToEvent(message, messageReturn, event);
1004 message = getCloserLeavingMessage(lifeline, startMessage, getAsyncMessages(), true);
1005 result = getCloserToEvent(result, message, event);
1006 messageReturn = getCloserLeavingMessage(lifeline, startMessage, getAsyncMessagesReturn(), true);
1007 result = getCloserToEvent(result, messageReturn, event);
1008 return result;
1009 }
1010
1011 /**
1012 * Get the first execution occurrence.
1013 *
1014 * @param lifeline A lifeline reference
1015 * @return the first execution occurrence of lifeline or <code>null</code>.
1016 */
1017 public BasicExecutionOccurrence getFirstExecution(Lifeline lifeline) {
1018 if (lifeline == null) {
1019 return null;
1020 }
1021 List<GraphNode> list = lifeline.getExecutions();
1022
1023 if ((list == null) || (list.isEmpty())) {
1024 return null;
1025 }
1026
1027 BasicExecutionOccurrence result = (BasicExecutionOccurrence) list.get(0);
1028 for (int i = 0; i < list.size(); i++) {
1029 BasicExecutionOccurrence e = (BasicExecutionOccurrence) list.get(i);
1030 if ((e.getStartOccurrence() < result.getEndOccurrence())) {
1031 result = e;
1032 }
1033 }
1034 return result;
1035 }
1036
1037 /**
1038 * Get the previous execution occurrence relative to a given execution occurrence.
1039 *
1040 * @param exec A execution occurrence reference.
1041 * @return the previous execution occurrence of lifeline or <code>null</code>.
1042 */
1043 public BasicExecutionOccurrence getPrevExecOccurrence(BasicExecutionOccurrence exec) {
1044 if (exec == null) {
1045 return null;
1046 }
1047 Lifeline lifeline = exec.getLifeline();
1048 if (lifeline == null) {
1049 return null;
1050 }
1051 List<GraphNode> list = lifeline.getExecutions();
1052 if (list == null) {
1053 return null;
1054 }
1055 BasicExecutionOccurrence result = null;
1056 for (int i = 0; i < list.size(); i++) {
1057 BasicExecutionOccurrence e = (BasicExecutionOccurrence) list.get(i);
1058 if ((e.getStartOccurrence() < exec.getStartOccurrence()) && (result == null)) {
1059 result = e;
1060 }
1061 if ((e.getStartOccurrence() < exec.getStartOccurrence()) && (result != null) && (e.getStartOccurrence() >= result.getEndOccurrence())) {
1062 result = e;
1063 }
1064 }
1065 return result;
1066 }
1067
1068 /**
1069 * Get the next execution occurrence relative to a given execution occurrence.
1070 *
1071 * @param exec A execution occurrence reference.
1072 * @return the next execution occurrence of lifeline or <code>null</code>.
1073 */
1074 public BasicExecutionOccurrence getNextExecOccurrence(BasicExecutionOccurrence exec) {
1075 if (exec == null) {
1076 return null;
1077 }
1078 Lifeline lifeline = exec.getLifeline();
1079 if (lifeline == null) {
1080 return null;
1081 }
1082 List<GraphNode> list = lifeline.getExecutions();
1083 if (list == null) {
1084 return null;
1085 }
1086 BasicExecutionOccurrence result = null;
1087 for (int i = 0; i < list.size(); i++) {
1088 BasicExecutionOccurrence e = (BasicExecutionOccurrence) list.get(i);
1089 if ((e.getStartOccurrence() > exec.getStartOccurrence()) && (result == null)) {
1090 result = e;
1091 }
1092 if ((e.getStartOccurrence() > exec.getStartOccurrence()) && (result != null) && (e.getStartOccurrence() <= result.getEndOccurrence())) {
1093 result = e;
1094 }
1095 }
1096 return result;
1097 }
1098
1099 /**
1100 * Get the last execution occurrence.
1101 *
1102 * @param lifeline A lifeline reference.
1103 * @return the last execution occurrence of lifeline or <code>null</code>.
1104 */
1105 public BasicExecutionOccurrence getLastExecOccurrence(Lifeline lifeline) {
1106 if (lifeline == null) {
1107 return null;
1108 }
1109 List<GraphNode> list = lifeline.getExecutions();
1110 if (list == null) {
1111 return null;
1112 }
1113 BasicExecutionOccurrence result = null;
1114 for (int i = 0; i < list.size(); i++) {
1115 BasicExecutionOccurrence e = (BasicExecutionOccurrence) list.get(i);
1116 if (result == null) {
1117 result = e;
1118 }
1119 if (e.getStartOccurrence() > result.getEndOccurrence()) {
1120 result = e;
1121 }
1122 }
1123 return result;
1124 }
1125
1126 /**
1127 * @return highlighted life line if set else null.
1128 */
1129 protected Lifeline getHighlightLifeline() {
1130 return fHighlightLifeline;
1131 }
1132
1133 /**
1134 * @return the start event value.
1135 */
1136 protected int getStartEvent() {
1137 return fStartEvent;
1138 }
1139
1140 /**
1141 * Returns the number of events
1142 *
1143 * @return the number of events
1144 */
1145 protected int getNumberOfEvents() {
1146 return fNbEvent;
1147 }
1148
1149 /**
1150 * Returns the highlight color.
1151 *
1152 * @return the highlight color
1153 */
1154 protected IColor getHighlightColor() {
1155 return fHighlightColor;
1156 }
1157
1158 /**
1159 * Set the highlighted life line.
1160 *
1161 * @param lifeline
1162 * The highlighted life line if set else null
1163 */
1164 protected void setHighlightLifeline(Lifeline lifeline) {
1165 fHighlightLifeline = lifeline;
1166 }
1167
1168 /**
1169 * Sets the start event value
1170 *
1171 * @param startEvent
1172 * the start event value.
1173 */
1174 protected void setStartEvent(int startEvent) {
1175 fStartEvent = startEvent;
1176 }
1177
1178 /**
1179 * Sets the number of events
1180 *
1181 * @param nbEvents
1182 * The number of events
1183 */
1184 protected void setNumberOfEvents(int nbEvents) {
1185 fNbEvent = nbEvents;
1186 }
1187
1188 /**
1189 * Sets the highlight color.
1190 *
1191 * @param color
1192 * the highlight color
1193 */
1194 protected void setHighlightColor(IColor color) {
1195 fHighlightColor = color;
1196 }
1197
1198 /**
1199 * sets the list of execution occurrences.
1200 *
1201 * @param occurences
1202 * the list of execution occurrences
1203 */
1204 protected void setExecutionOccurrencesWithTime(List<SDTimeEvent> occurences) {
1205 fExecutionOccurrencesWithTime = occurences;
1206 }
1207 }
This page took 0.080808 seconds and 5 git commands to generate.