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