Merge branch 'master' into TmfEventModel
[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, 2011 IBM Corporation and others.
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 * $Id: Frame.java,v 1.3 2008/01/24 02:28:49 apnan Exp $
8 *
9 * Contributors:
10 * IBM - Initial API and implementation
11 * Bernd Hufmann - Updated for TMF
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.event.ITmfTimestamp;
21 import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
22 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IColor;
23 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC;
24 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.preferences.SDViewPref;
25 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.util.TimeEventComparator;
26
27 /**
28 * The Frame class is the base sequence diagram graph nodes container.<br>
29 * For instance, only one frame can be drawn in the View.<br>
30 * Lifelines, Messages and Stop which are supposed to represent a Sequence diagram are drawn in a Frame.<br>
31 * Only the graph node added to their representing list will be drawn.
32 *
33 * The lifelines are appended along the X axsis when added in a frame.<br>
34 * The syncMessages are ordered along the Y axsis depending on the event occurrence they are attached to.<br>
35 *
36 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Lifeline Lifeline for more event occurence details
37 * @author sveyrier
38 * @version 1.0
39 */
40 public class Frame extends BasicFrame {
41
42 protected Lifeline highlightLifeline = null;
43 protected int startEvent = 0;
44 protected int nbEvent = 0;
45 protected IColor highlightColor = null;
46
47 protected List<SDTimeEvent> executionOccurrencesWithTime;
48
49 protected LifelineCategories[] lifelineCategories = null;
50
51 /**
52 * Returns a list of all lifelines known by this frame. Known lifelines are the only one which can be displayed on
53 * screen.
54 *
55 * @return the lifelines list
56 */
57 protected List<GraphNode> getLifelines() {
58 if (!hasChilden)
59 return null;
60 else
61 return (List<GraphNode>) nodes.get(Lifeline.LIFELINE_TAG);
62 }
63
64 /**
65 * Returns the number of lifelines stored in the frame
66 *
67 * @return the number of lifelines
68 */
69 public int lifeLinesCount() {
70 List<GraphNode> lifelines = getLifelines();
71 if (lifelines != null)
72 return lifelines.size();
73 else
74 return 0;
75 }
76
77 /**
78 * Returns the lifeline at the given index in the lifelines array
79 *
80 * @param index the position in the lifeline array
81 * @return the lifeline
82 */
83 public Lifeline getLifeline(int index) {
84 if ((getLifelines() != null) && (index >= 0) && (index < lifeLinesCount()))
85 return (Lifeline) getLifelines().get(index);
86 return null;
87 }
88
89 /**
90 * Returns a list of syncMessages known by this frame. Known syncMessages are the only on which can be displayed on
91 * screen
92 *
93 * @return the syncMessages list
94 */
95 protected List<GraphNode> getSyncMessages() {
96 if (!hasChilden)
97 return null;
98 else
99 return (List<GraphNode>) nodes.get(SyncMessage.SYNC_MESS_TAG);
100 }
101
102 /**
103 * Returns the number of syncMessages stored in the frame
104 *
105 * @return the number of syncMessage
106 */
107 public int syncMessageCount() {
108 if (getSyncMessages() != null)
109 return getSyncMessages().size();
110 else
111 return 0;
112 }
113
114 /**
115 * Returns the syncMessage at the given index in the syncMessages array
116 *
117 * @param index the position in the syncMessages array
118 * @return the syncMessage
119 */
120 public SyncMessage getSyncMessage(int index) {
121 if ((getSyncMessages() != null) && (index >= 0) && (index < getSyncMessages().size()))
122 return (SyncMessage) getSyncMessages().get(index);
123 return null;
124 }
125
126 /**
127 * Returns a list of asyncMessages known by this frame. Known asyncMessages are the only on which can be displayed
128 * on screen
129 *
130 * @return the asyncMessages list
131 */
132 protected List<GraphNode> getAsyncMessages() {
133 if (!hasChilden)
134 return null;
135 else
136 return (List<GraphNode>) nodes.get(AsyncMessage.ASYNC_MESS_TAG);
137 }
138
139 /**
140 * Returns the number of asyncMessage stored in the frame
141 *
142 * @return the number of asyncMessage
143 */
144 public int asyncMessageCount() {
145 if (getAsyncMessages() != null)
146 return getAsyncMessages().size();
147 else
148 return 0;
149 }
150
151 /**
152 * Returns the asyncMessage at the given index in the asyncMessage array
153 *
154 * @param index the position in the asyncMessage array
155 * @return the asyncMessage
156 */
157 public AsyncMessage getAsyncMessage(int index) {
158 if ((getAsyncMessages() != null) && (index >= 0) && (index < getAsyncMessages().size()))
159 return (AsyncMessage) getAsyncMessages().get(index);
160 return null;
161 }
162
163 /**
164 * Returns a list of syncMessages return known by this frame. Known syncMessages return are the only on which can be
165 * displayed on screen
166 *
167 * @return the syncMessages return list
168 */
169 protected List<GraphNode> getSyncMessagesReturn() {
170 if (!hasChilden)
171 return null;
172 else
173 return (List<GraphNode>) nodes.get(SyncMessageReturn.SYNC_MESS_RET_TAG);
174 }
175
176 /**
177 * Returns the number of syncMessageReturn stored in the frame
178 *
179 * @return the number of syncMessageReturn
180 */
181 public int syncMessageReturnCount() {
182 if (getSyncMessagesReturn() != null)
183 return getSyncMessagesReturn().size();
184 else
185 return 0;
186 }
187
188 /**
189 * Returns the syncMessageReturn at the given index in the syncMessageReturn array
190 *
191 * @param index the position in the syncMessageReturn array
192 * @return the syncMessageReturn
193 */
194 public SyncMessageReturn getSyncMessageReturn(int index) {
195 if ((getSyncMessagesReturn() != null) && (index >= 0) && (index < getSyncMessagesReturn().size()))
196 return (SyncMessageReturn) getSyncMessagesReturn().get(index);
197 return null;
198 }
199
200 /**
201 * Returns a list of asyncMessageRetun known by this frame. Known asyncMessageRetun are the only on which can be
202 * displayed on screen
203 *
204 * @return the asyncMessageRetun list
205 */
206 protected List<GraphNode> getAsyncMessagesReturn() {
207 if (!hasChilden)
208 return null;
209 else
210 return (List<GraphNode>) nodes.get(AsyncMessageReturn.ASYNC_MESS_RET_TAG);
211 }
212
213 /**
214 * Returns the number of asyncMessageReturn stored in the frame
215 *
216 * @return the number of asyncMessageReturn
217 */
218 public int asyncMessageReturnCount() {
219 if (getAsyncMessagesReturn() != null)
220 return getAsyncMessagesReturn().size();
221 else
222 return 0;
223 }
224
225 /**
226 * Returns the asyncMessageReturn at the given index in the asyncMessageReturn array
227 *
228 * @param index the position in the asyncMessageReturn array
229 * @return the asyncMessageReturn
230 */
231 public AsyncMessageReturn getAsyncMessageReturn(int index) {
232 if ((getAsyncMessagesReturn() != null) && (index >= 0) && (index < getAsyncMessagesReturn().size()))
233 return (AsyncMessageReturn) getAsyncMessagesReturn().get(index);
234 return null;
235 }
236
237 /**
238 * Adds a lifeline to the frame lifelines list. The lifeline X drawing order depends on the lifeline addition order
239 * into the frame lifelines list.
240 *
241 * @param the lifeline to add
242 */
243 public void addLifeLine(Lifeline lifeLine) {
244 computeMinMax = true;
245 if (lifeLine == null)
246 return;
247 // set the lifeline parent frame
248 lifeLine.setFrame(this);
249 // Increate the frame lifeline counter
250 // and set the lifeline drawing order
251 lifeLine.setIndex(getNewHorizontalIndex());
252 if (lifeLine.hasTimeInfo()) {
253 timeInfo = true;
254 }
255 // add the lifeline to the lifelines list
256 addNode(lifeLine);
257 }
258
259 /**
260 * Returns the first visible lifeline drawn in the view
261 *
262 * @return the first visible lifeline index
263 */
264 public int getFirstVisibleLifeline() {
265 if (!hasChilden)
266 return 0;
267 else if (indexes.get(Lifeline.LIFELINE_TAG) != null)
268 return ((Integer) indexes.get(Lifeline.LIFELINE_TAG)).intValue();
269 else
270 return 0;
271 }
272
273 /**
274 * Returns the first visible synchronous message drawn in the view
275 *
276 * @return the first visible synchronous message index
277 */
278 public int getFirstVisibleSyncMessage() {
279 if (!hasChilden)
280 return 0;
281 else if (indexes.get(SyncMessage.SYNC_MESS_TAG) != null)
282 return ((Integer) indexes.get(SyncMessage.SYNC_MESS_TAG)).intValue();
283 else
284 return 0;
285 }
286
287 /**
288 * Returns the first visible synchronous message return drawn in the view
289 *
290 * @return the first visible synchronous message return index
291 */
292 public int getFirstVisibleSyncMessageReturn() {
293 if (!hasChilden)
294 return 0;
295 else if (indexes.get(SyncMessageReturn.SYNC_MESS_RET_TAG) != null)
296 return ((Integer) indexes.get(SyncMessageReturn.SYNC_MESS_RET_TAG)).intValue();
297 else
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 getFirstVisibleAsyncMessage() {
307 if (!hasChilden)
308 return 0;
309 else if (indexes.get(AsyncMessage.ASYNC_MESS_TAG) != null)
310 return ((Integer) indexes.get(AsyncMessage.ASYNC_MESS_TAG)).intValue();
311 else
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 getFirstVisibleAsyncMessageReturn() {
321 if (!hasChilden)
322 return 0;
323 else if (indexes.get(AsyncMessageReturn.ASYNC_MESS_RET_TAG) != null)
324 return ((Integer) indexes.get(AsyncMessageReturn.ASYNC_MESS_RET_TAG)).intValue();
325 else
326 return 0;
327 }
328
329 public List<SDTimeEvent> getExecutionOccurrencesWithTime() {
330 return executionOccurrencesWithTime;
331 }
332
333 public void insertLifelineAfter(Lifeline toInsert, Lifeline after) {
334 if ((toInsert == null))
335 return;
336 if (toInsert == after)
337 return;
338 int insertPoint = 0;
339 if (after != null)
340 insertPoint = after.getIndex();
341 int removePoint = toInsert.getIndex() - 1;
342 if (removePoint >= insertPoint)
343 getLifelines().remove(removePoint);
344 getLifelines().add(insertPoint, toInsert);
345 if (removePoint < insertPoint)
346 getLifelines().remove(removePoint);
347
348 if (removePoint >= insertPoint)
349 toInsert.setIndex(insertPoint + 1);
350 else
351 toInsert.setIndex(insertPoint - 1);
352
353 insertPoint++;
354 if (removePoint >= insertPoint) {
355 for (int i = insertPoint; i < getLifelines().size(); i++) {
356 getLifeline(i).setIndex(i + 1);
357 }
358 } else {
359 for (int i = 0; i < insertPoint && i < getLifelines().size(); i++) {
360 getLifeline(i).setIndex(i + 1);
361 }
362 }
363 }
364
365 public void insertLifelineBefore(Lifeline toInsert, Lifeline before) {
366 if ((toInsert == null))
367 return;
368 if (toInsert == before)
369 return;
370 int insertPoint = 0;
371 if (before != null)
372 insertPoint = before.getIndex() - 1;
373 int removePoint = toInsert.getIndex() - 1;
374 if (removePoint >= insertPoint)
375 getLifelines().remove(removePoint);
376 getLifelines().add(insertPoint, toInsert);
377 if (removePoint < insertPoint)
378 getLifelines().remove(removePoint);
379
380 if (removePoint >= insertPoint)
381 toInsert.setIndex(insertPoint + 1);
382 else
383 toInsert.setIndex(insertPoint - 1);
384
385 insertPoint++;
386 if (removePoint >= insertPoint) {
387 for (int i = insertPoint; i < getLifelines().size(); i++) {
388 getLifeline(i).setIndex(i + 1);
389 }
390 } else {
391 for (int i = 0; i < insertPoint && i < getLifelines().size(); i++) {
392 getLifeline(i).setIndex(i + 1);
393 }
394 }
395 }
396
397 public Lifeline getCloserLifeline(int x) {
398 int index = (x - Metrics.FRAME_H_MARGIN + Metrics.LIFELINE_H_MAGIN) / Metrics.swimmingLaneWidth() - 1;
399 if (index < 0)
400 index = 0;
401 if (index >= getLifelines().size())
402 index = getLifelines().size() - 1;
403 Lifeline node1, node2, node3;
404 int dist1, dist2, dist3;
405 node1 = node2 = node3 = getLifeline(index);
406 dist1 = dist2 = dist3 = Math.abs(node1.getX() + node1.getWidth() / 2 - x);
407 if (index > 0) {
408 node2 = getLifeline(index - 1);
409 dist2 = Math.abs(node2.getX() + node2.getWidth() / 2 - x);
410 }
411 if (index < getLifelines().size() - 1) {
412 node3 = getLifeline(index + 1);
413 dist3 = Math.abs(node3.getX() + node3.getWidth() / 2 - x);
414 }
415 if (dist1 <= dist2 && dist1 <= dist3)
416 return node1;
417 else if (dist2 <= dist1 && dist2 <= dist3)
418 return node2;
419 else
420 return node3;
421 }
422
423 public void reorder(ArrayList<?> list) {
424 for (int i = 0; i < list.size(); i++) {
425 if (list.get(i) instanceof Lifeline[]) {
426 Lifeline temp[] = (Lifeline[]) list.get(i);
427 if (temp.length == 2) {
428 if (temp[1] == null) {
429 insertLifelineAfter(temp[0], getLifeline(lifeLinesCount() - 1));
430 } else
431 insertLifelineBefore(temp[0], temp[1]);
432 }
433 }
434 }
435 }
436
437 public void resetTimeCompression() {
438 highlightLifeline = null;
439 this.startEvent = 0;
440 this.nbEvent = 0;
441 highlightColor = null;
442 }
443
444 @Override
445 protected void computeMinMax() {
446 List<SDTimeEvent> timeArray = buildTimeArray();
447 if (timeArray == null)
448 return;
449 for (int i = 0; i < timeArray.size() - 1; i++) {
450 SDTimeEvent m1 = (SDTimeEvent) timeArray.get(i);
451 SDTimeEvent m2 = (SDTimeEvent) timeArray.get(i + 1);
452 if (SDViewPref.getInstance().excludeExternalTime())
453 if ((m1.getGraphNode() instanceof BaseMessage) && (m2.getGraphNode() instanceof BaseMessage)) {
454 BaseMessage mes1 = (BaseMessage) m1.getGraphNode();
455 BaseMessage mes2 = (BaseMessage) m2.getGraphNode();
456 if ((mes2.startLifeline == null) || (mes1.endLifeline == null))
457 continue;
458 }
459
460 updateMinMax(m1, m2);
461 }
462 }
463
464 /**
465 * Find the two graph nodes that are closest to this date, one just earlier, second just later. If date is before
466 * any graph node, bounds[0] is null and bounds[1] is the earliest. If date is after any graph node, bounds[1] is
467 * null and bounds[0] is the latest.
468 *
469 * @param dateToFind date to be found
470 * @param bounds a two items array that will receive bounds if found
471 * @return true if both bounds not null
472 */
473 public boolean findDateBounds(TmfTimestamp dateToFind, ITimeRange bounds[]) {
474 if (hasTimeInfo()) {
475 List<SDTimeEvent> timeArray = buildTimeArray();
476 bounds[0] = null;
477 bounds[1] = null;
478 for (int i = 0; i < timeArray.size(); i++) {
479 SDTimeEvent m = (SDTimeEvent) timeArray.get(i);
480 if (m.getTime().compareTo(dateToFind, true) > 0) {
481 bounds[1] = m.getGraphNode();
482 if (i > 0) {
483 bounds[0] = ((SDTimeEvent) timeArray.get(i - 1)).getGraphNode();
484 return true;
485 }
486 return false;
487 }
488 }
489 bounds[0] = ((SDTimeEvent) timeArray.get(timeArray.size() - 1)).getGraphNode();
490 }
491 return false;
492 }
493
494 protected void setHasTimeInfo(boolean value) {
495 timeInfo = value;
496 }
497
498 /**
499 * @return true if frame has time info else false
500 */
501 public boolean hasTimeInfo() {
502 return timeInfo;
503 }
504
505 /**
506 * @param lifeline
507 * @param startEvent
508 * @param nbEvent
509 * @param color
510 */
511 public void highlightTimeCompression(Lifeline lifeline, int startEvent, int nbEvent, IColor color) {
512 highlightLifeline = lifeline;
513 this.startEvent = startEvent;
514 this.nbEvent = nbEvent;
515 highlightColor = color;
516 }
517
518 /**
519 * Set the lifeline categories which will be use during the lifelines creation
520 *
521 * @see Lifeline#setCategory(int)
522 * @param categories the lifeline categories array
523 */
524 public void setLifelineCategories(LifelineCategories[] categories) {
525 lifelineCategories = Arrays.copyOf(categories, categories.length);
526 }
527
528 /**
529 * Returns the lifeline categories array set for the this frame
530 *
531 * @return the lifeline categories array or null if not set
532 */
533 public LifelineCategories[] getLifelineCategories() {
534 return Arrays.copyOf(lifelineCategories, lifelineCategories.length);
535 }
536
537 /**
538 * Adds a message to the Frame message list. Four kinds of syncMessages can be added:<br>
539 * - synchronous syncMessages<br>
540 * - synchronous syncMessages return<br>
541 * - asynchronous syncMessages<br>
542 * - asynchronous syncMessages return<br>
543 * For drawing performance reason, it is recommended to add synchronous syncMessages in the same order they should
544 * appear along the Y axis in the Frame.
545 *
546 * @param the message to add
547 */
548 public void addMessage(BaseMessage message) {
549 addNode(message);
550 }
551
552 @Override
553 public void draw(IGC context) {
554 drawFrame(context);
555 if (!hasChilden)
556 return;
557
558 if (highlightLifeline != null) {
559 IColor backupColor = context.getBackground();
560 context.setBackground(Frame.getUserPref().getTimeCompressionSelectionColor());
561 int gy = highlightLifeline.getY() + highlightLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * startEvent;
562 context.fillRectangle(Metrics.FRAME_H_MARGIN + 1, gy, highlightLifeline.getX() + Metrics.getLifelineWidth() / 2 - Metrics.FRAME_H_MARGIN, (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * nbEvent);
563 context.setBackground(backupColor);
564 }
565 super.draw(context, false);
566 int lifelineArryStep = 1;
567 if (Metrics.swimmingLaneWidth() * context.getZoom() < Metrics.LIFELINE_SIGNIFICANT_HSPACING)
568 lifelineArryStep = Math.round(Metrics.LIFELINE_SIGNIFICANT_HSPACING / (Metrics.swimmingLaneWidth() * context.getZoom()));
569 if (indexes.size() == 0)
570 return;
571 int lifeLineDrawIndex = ((Integer) indexes.get(Lifeline.LIFELINE_TAG)).intValue();
572 for (int i = lifeLineDrawIndex; i < ((List<GraphNode>) nodes.get(Lifeline.LIFELINE_TAG)).size(); i = i + lifelineArryStep) {
573 Lifeline toDraw = (Lifeline) ((List<GraphNode>) nodes.get(Lifeline.LIFELINE_TAG)).get(i);
574 if (toDraw.getX() - Metrics.LIFELINE_SPACING / 2 > context.getContentsX() + context.getVisibleWidth())
575 break;
576 toDraw.drawName(context);
577
578 if (highlightLifeline != null) {
579 if (toDraw == highlightLifeline)
580 toDraw.highlightExecOccurrenceRegion(context, startEvent, nbEvent, highlightColor);
581 else if ((toDraw.getIndex() < highlightLifeline.getIndex()) || ((toDraw.getIndex() < highlightLifeline.getIndex()))) {
582
583 int acIndex = toDraw.getExecOccurrenceDrawIndex();
584 // acIndex = first visible execution occurrence
585 // for drawing speed reason with only search on the visible subset
586 if (toDraw.getExecutions() != null)
587 for (int index = acIndex; index < toDraw.getExecutions().size(); index++) {
588 BasicExecutionOccurrence exec = (BasicExecutionOccurrence) toDraw.getExecutions().get(index);
589 int tempEvent = startEvent;
590 for (int j = 0; j < nbEvent; j++) {
591 if (((tempEvent >= exec.startEventOccurrence) && (tempEvent <= exec.endEventOccurrence) && (tempEvent + 1 >= exec.startEventOccurrence) && (tempEvent + 1 <= exec.endEventOccurrence))) {
592 toDraw.highlightExecOccurrenceRegion(context, tempEvent, 1, Frame.getUserPref().getTimeCompressionSelectionColor());
593 }
594 tempEvent = tempEvent + 1;
595 }
596 // if we are outside the visible area we stop right now
597 // This works because execution occurrences are ordered along the Y axis
598 if (exec.getY() > getY())
599 break;
600 }
601 }
602 }
603 }
604 }
605
606 @Override
607 protected List<SDTimeEvent> buildTimeArray() {
608 if (!hasChilden)
609 return null;
610 try {
611 List<SDTimeEvent> timeArray = super.buildTimeArray();
612 executionOccurrencesWithTime = null;
613 if (getLifelines() != null)
614 for (int i = 0; i < ((List<GraphNode>) nodes.get(Lifeline.LIFELINE_TAG)).size(); i++) {
615 Lifeline l = (Lifeline) ((List<GraphNode>) nodes.get(Lifeline.LIFELINE_TAG)).get(i);
616 if (l.hasTimeInfo() && l.getExecutions() != null) {
617 for (Iterator<GraphNode> j = l.getExecutions().iterator(); j.hasNext();) {
618 GraphNode o = j.next();
619 if (o instanceof ExecutionOccurrence) {
620 ExecutionOccurrence eo = (ExecutionOccurrence) o;
621 if (eo.hasTimeInfo()) {
622 int event = eo.getStartOccurrence();
623 ITmfTimestamp time = eo.getStartTime();
624 SDTimeEvent f = new SDTimeEvent(time, event, eo);
625 timeArray.add(f);
626 if (executionOccurrencesWithTime == null) {
627 executionOccurrencesWithTime = new ArrayList<SDTimeEvent>();
628 }
629 executionOccurrencesWithTime.add(f);
630 event = eo.getEndOccurrence();
631 time = eo.getEndTime();
632 f = new SDTimeEvent(time, event, eo);
633 timeArray.add(f);
634 executionOccurrencesWithTime.add(f);
635 }
636 }
637 }
638 }
639 }
640
641 if (executionOccurrencesWithTime != null) {
642 SDTimeEvent[] temp = executionOccurrencesWithTime.toArray(new SDTimeEvent[0]);
643 Arrays.sort(temp, new TimeEventComparator());
644 executionOccurrencesWithTime = Arrays.asList(temp);
645 }
646 SDTimeEvent[] temp = timeArray.toArray(new SDTimeEvent[0]);
647 Arrays.sort(temp, new TimeEventComparator());
648 timeArray = Arrays.asList(temp);
649 return timeArray;
650 } catch (Exception e) {
651 e.printStackTrace();
652 return null;
653 }
654
655 }
656
657 protected GraphNode getCloserLeavingMessage(Lifeline lifeline, BaseMessage message, List<GraphNode> list, boolean smallerEvent) {
658 if (list == null)
659 return null;
660 if (smallerEvent == false) {
661 int event = 0;
662 if (message != null)
663 event = message.getEventOccurrence();
664 for (int i = 0; i < list.size(); i++) {
665 GraphNode node = (GraphNode) list.get(i);
666 if (node instanceof SyncMessage) {
667 SyncMessage syncNode = (SyncMessage) node;
668 if ((syncNode.getEventOccurrence() > event) && (syncNode.getStartLifeline() == lifeline) && !syncNode.isSameAs(message))
669 return node;
670 } else if (node instanceof AsyncMessage) {
671 AsyncMessage asyncNode = (AsyncMessage) node;
672 if ((asyncNode.getStartOccurrence() > event) && (asyncNode.getStartLifeline() == lifeline) && !asyncNode.isSameAs(message))
673 return node;
674 }
675 }
676 } else {
677 int event = getMaxEventOccurrence();
678 if (message != null)
679 if (message instanceof AsyncMessage) {
680 event = ((AsyncMessage) message).getStartOccurrence();
681 } else
682 event = message.getEventOccurrence();
683 for (int i = list.size() - 1; i >= 0; i--) {
684 GraphNode node = (GraphNode) list.get(i);
685 if (node instanceof SyncMessage) {
686 SyncMessage syncNode = (SyncMessage) node;
687 if ((syncNode.getEventOccurrence() < event) && (syncNode.getStartLifeline() == lifeline) && !syncNode.isSameAs(message))
688 return node;
689 } else if (node instanceof AsyncMessage) {
690 AsyncMessage asyncNode = (AsyncMessage) node;
691 if ((asyncNode.getStartOccurrence() < event) && (asyncNode.getStartLifeline() == lifeline) && !asyncNode.isSameAs(message))
692 return node;
693 }
694 }
695 }
696 return null;
697 }
698
699 protected GraphNode getCloserEnteringMessage(Lifeline lifeline, BaseMessage message, List<GraphNode> list, boolean smallerEvent) {
700 if (list == null)
701 return null;
702 if (smallerEvent == false) {
703 int event = 0;
704 if (message != null)
705 event = message.getEventOccurrence();
706 for (int i = 0; i < list.size(); i++) {
707 GraphNode node = (GraphNode) list.get(i);
708 if (node instanceof SyncMessage) {
709 SyncMessage syncNode = (SyncMessage) node;
710 if ((syncNode.getEventOccurrence() > event) && (syncNode.getEndLifeline() == lifeline) && !syncNode.isSameAs(message))
711 return node;
712 } else if (node instanceof AsyncMessage) {
713 AsyncMessage asyncNode = (AsyncMessage) node;
714 if ((asyncNode.getStartOccurrence() > event) && (asyncNode.getEndLifeline() == lifeline) && !asyncNode.isSameAs(message))
715 return node;
716 }
717 }
718 } else {
719 int event = getMaxEventOccurrence();
720 if (message != null)
721 if (message instanceof AsyncMessage) {
722 event = ((AsyncMessage) message).getStartOccurrence();
723 } else
724 event = message.getEventOccurrence();
725 for (int i = list.size() - 1; i >= 0; i--) {
726 GraphNode node = (GraphNode) list.get(i);
727 if (node instanceof SyncMessage) {
728 SyncMessage syncNode = (SyncMessage) node;
729 if ((syncNode.getEventOccurrence() < event) && (syncNode.getEndLifeline() == lifeline) && !syncNode.isSameAs(message))
730 return node;
731 } else if (node instanceof AsyncMessage) {
732 AsyncMessage asyncNode = (AsyncMessage) node;
733 if ((asyncNode.getStartOccurrence() < event) && (asyncNode.getEndLifeline() == lifeline) && !asyncNode.isSameAs(message))
734 return node;
735 }
736 }
737 }
738 return null;
739 }
740
741 protected int distanceFromEvent(GraphNode node, int event) {
742 int distance = 0;
743 if (node instanceof SyncMessage)
744 distance = ((SyncMessage) node).getEventOccurrence() - event;
745 else if (node instanceof AsyncMessage) {
746 int start = ((AsyncMessage) node).getStartOccurrence();
747 int end = ((AsyncMessage) node).getEndOccurrence();
748 if ((start - event) < (end - event))
749 distance = start - event;
750 else
751 distance = end - event;
752 }
753 return Math.abs(distance);
754 }
755
756 protected GraphNode getCloserToEvent(GraphNode node1, GraphNode node2, int event) {
757 if ((node1 != null) && (node2 != null)) {
758 if (distanceFromEvent(node1, event) < distanceFromEvent(node2, event))
759 return node1;
760 else
761 return node2;
762 } else if (node1 != null)
763 return node1;
764 else if (node2 != null)
765 return node2;
766 else
767 return null;
768 }
769
770 public GraphNode getCalledMessage(BaseMessage StartMessage) {
771 int event = 0;
772 GraphNode result = null;
773 Lifeline lifeline = null;
774 if (StartMessage != null) {
775 event = ((BaseMessage) StartMessage).getEventOccurrence();
776 lifeline = ((BaseMessage) StartMessage).getEndLifeline();
777 if (lifeline == null)
778 lifeline = ((BaseMessage) StartMessage).getStartLifeline();
779 }
780 if (lifeline == null)
781 return null;
782 GraphNode message = getCloserLeavingMessage(lifeline, StartMessage, getSyncMessages(), false);
783 GraphNode messageReturn = getCloserLeavingMessage(lifeline, StartMessage, getSyncMessagesReturn(), false);
784 result = getCloserToEvent(message, messageReturn, event);
785 message = getCloserLeavingMessage(lifeline, StartMessage, getAsyncMessages(), false);
786 result = getCloserToEvent(result, message, event);
787 messageReturn = getCloserLeavingMessage(lifeline, StartMessage, getAsyncMessagesReturn(), false);
788 result = getCloserToEvent(result, messageReturn, event);
789 return result;
790 }
791
792 public GraphNode getCallerMessage(BaseMessage StartMessage) {
793 int event = getMaxEventOccurrence();
794 GraphNode result = null;
795 Lifeline lifeline = null;
796 if (StartMessage != null) {
797 event = ((BaseMessage) StartMessage).getEventOccurrence();
798 lifeline = ((BaseMessage) StartMessage).getStartLifeline();
799 if (lifeline == null)
800 lifeline = ((BaseMessage) StartMessage).getEndLifeline();
801 }
802 if (lifeline == null)
803 return null;
804 GraphNode message = getCloserEnteringMessage(lifeline, StartMessage, getSyncMessages(), true);
805 GraphNode messageReturn = getCloserEnteringMessage(lifeline, StartMessage, getSyncMessagesReturn(), true);
806 result = getCloserToEvent(message, messageReturn, event);
807 message = getCloserEnteringMessage(lifeline, StartMessage, getAsyncMessages(), true);
808 result = getCloserToEvent(result, message, event);
809 messageReturn = getCloserEnteringMessage(lifeline, StartMessage, getAsyncMessagesReturn(), true);
810 result = getCloserToEvent(result, messageReturn, event);
811 return result;
812 }
813
814 public GraphNode getNextLifelineMessage(Lifeline lifeline, BaseMessage StartMessage) {
815 int event = 0;
816 if (StartMessage != null)
817 event = ((BaseMessage) StartMessage).getEventOccurrence();
818 if (lifeline == null)
819 return null;
820 GraphNode message = getCloserLeavingMessage(lifeline, StartMessage, getSyncMessages(), false);
821 GraphNode messageReturn = getCloserLeavingMessage(lifeline, StartMessage, getSyncMessagesReturn(), false);
822 GraphNode result = getCloserToEvent(message, messageReturn, event);
823 message = getCloserLeavingMessage(lifeline, StartMessage, getAsyncMessages(), false);
824 result = getCloserToEvent(result, message, event);
825 messageReturn = getCloserLeavingMessage(lifeline, StartMessage, getAsyncMessagesReturn(), false);
826 result = getCloserToEvent(result, messageReturn, event);
827 return result;
828 }
829
830 public BasicExecutionOccurrence getFirstExecution(Lifeline lifeline) {
831 if (lifeline == null)
832 return null;
833 List<GraphNode> list = lifeline.getExecutions();
834 if (list == null)
835 return null;
836 if (list.size() == 0)
837 return null;
838 BasicExecutionOccurrence result = (BasicExecutionOccurrence) list.get(0);
839 for (int i = 0; i < list.size(); i++) {
840 BasicExecutionOccurrence e = (BasicExecutionOccurrence) list.get(i);
841 if ((e.getStartOccurrence() < result.getEndOccurrence()))
842 result = e;
843 }
844 return result;
845 }
846
847 public BasicExecutionOccurrence getPrevExecOccurrence(BasicExecutionOccurrence exec) {
848 if (exec == null)
849 return null;
850 Lifeline lifeline = exec.getLifeline();
851 if (lifeline == null)
852 return null;
853 List<GraphNode> list = lifeline.getExecutions();
854 if (list == null)
855 return null;
856 BasicExecutionOccurrence result = null;
857 for (int i = 0; i < list.size(); i++) {
858 BasicExecutionOccurrence e = (BasicExecutionOccurrence) list.get(i);
859 if ((e.getStartOccurrence() < exec.startEventOccurrence) && (result == null))
860 result = e;
861 if ((e.getStartOccurrence() < exec.startEventOccurrence) && (e.getStartOccurrence() >= result.getEndOccurrence()))
862 result = e;
863 }
864 return result;
865 }
866
867 public BasicExecutionOccurrence getNextExecOccurrence(BasicExecutionOccurrence exec) {
868 if (exec == null)
869 return null;
870 Lifeline lifeline = exec.getLifeline();
871 if (lifeline == null)
872 return null;
873 List<GraphNode> list = lifeline.getExecutions();
874 if (list == null)
875 return null;
876 BasicExecutionOccurrence result = null;
877 for (int i = 0; i < list.size(); i++) {
878 BasicExecutionOccurrence e = (BasicExecutionOccurrence) list.get(i);
879 if ((e.getStartOccurrence() > exec.startEventOccurrence) && (result == null))
880 result = e;
881 if ((e.getStartOccurrence() > exec.startEventOccurrence) && (e.getStartOccurrence() <= result.getEndOccurrence()))
882 result = e;
883 }
884 return result;
885 }
886
887 public BasicExecutionOccurrence getLastExecOccurrence(Lifeline lifeline) {
888 if (lifeline == null)
889 return null;
890 List<GraphNode> list = lifeline.getExecutions();
891 if (list == null)
892 return null;
893 BasicExecutionOccurrence result = null;
894 for (int i = 0; i < list.size(); i++) {
895 BasicExecutionOccurrence e = (BasicExecutionOccurrence) list.get(i);
896 if (result == null)
897 result = e;
898 if (e.getStartOccurrence() > result.getEndOccurrence())
899 result = e;
900 }
901 return result;
902 }
903
904 public GraphNode getPrevLifelineMessage(Lifeline lifeline, BaseMessage StartMessage) {
905 int event = getMaxEventOccurrence();
906 if (StartMessage != null)
907 if (StartMessage instanceof AsyncMessage) {
908 event = ((AsyncMessage) StartMessage).getStartOccurrence();
909 } else
910 event = StartMessage.getEventOccurrence();
911 if (lifeline == null)
912 return null;
913 GraphNode message = getCloserLeavingMessage(lifeline, StartMessage, getSyncMessages(), true);
914 GraphNode messageReturn = getCloserLeavingMessage(lifeline, StartMessage, getSyncMessagesReturn(), true);
915 GraphNode result = getCloserToEvent(message, messageReturn, event);
916 message = getCloserLeavingMessage(lifeline, StartMessage, getAsyncMessages(), true);
917 result = getCloserToEvent(result, message, event);
918 messageReturn = getCloserLeavingMessage(lifeline, StartMessage, getAsyncMessagesReturn(), true);
919 result = getCloserToEvent(result, messageReturn, event);
920 return result;
921 }
922 }
This page took 0.060101 seconds and 6 git commands to generate.