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