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 $
10 * IBM - Initial API and implementation
11 * Bernd Hufmann - Updated for TMF
12 **********************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.core
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Arrays
;
17 import java
.util
.Iterator
;
18 import java
.util
.List
;
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
;
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.
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>
36 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Lifeline Lifeline for more event occurence details
40 public class Frame
extends BasicFrame
{
42 protected Lifeline highlightLifeline
= null;
43 protected int startEvent
= 0;
44 protected int nbEvent
= 0;
45 protected IColor highlightColor
= null;
47 protected List
<SDTimeEvent
> executionOccurrencesWithTime
;
49 protected LifelineCategories
[] lifelineCategories
= null;
52 * Returns a list of all lifelines known by this frame. Known lifelines are the only one which can be displayed on
55 * @return the lifelines list
57 protected List
<GraphNode
> getLifelines() {
61 return (List
<GraphNode
>) nodes
.get(Lifeline
.LIFELINE_TAG
);
65 * Returns the number of lifelines stored in the frame
67 * @return the number of lifelines
69 public int lifeLinesCount() {
70 List
<GraphNode
> lifelines
= getLifelines();
71 if (lifelines
!= null)
72 return lifelines
.size();
78 * Returns the lifeline at the given index in the lifelines array
80 * @param index the position in the lifeline array
81 * @return the lifeline
83 public Lifeline
getLifeline(int index
) {
84 if ((getLifelines() != null) && (index
>= 0) && (index
< lifeLinesCount()))
85 return (Lifeline
) getLifelines().get(index
);
90 * Returns a list of syncMessages known by this frame. Known syncMessages are the only on which can be displayed on
93 * @return the syncMessages list
95 protected List
<GraphNode
> getSyncMessages() {
99 return (List
<GraphNode
>) nodes
.get(SyncMessage
.SYNC_MESS_TAG
);
103 * Returns the number of syncMessages stored in the frame
105 * @return the number of syncMessage
107 public int syncMessageCount() {
108 if (getSyncMessages() != null)
109 return getSyncMessages().size();
115 * Returns the syncMessage at the given index in the syncMessages array
117 * @param index the position in the syncMessages array
118 * @return the syncMessage
120 public SyncMessage
getSyncMessage(int index
) {
121 if ((getSyncMessages() != null) && (index
>= 0) && (index
< getSyncMessages().size()))
122 return (SyncMessage
) getSyncMessages().get(index
);
127 * Returns a list of asyncMessages known by this frame. Known asyncMessages are the only on which can be displayed
130 * @return the asyncMessages list
132 protected List
<GraphNode
> getAsyncMessages() {
136 return (List
<GraphNode
>) nodes
.get(AsyncMessage
.ASYNC_MESS_TAG
);
140 * Returns the number of asyncMessage stored in the frame
142 * @return the number of asyncMessage
144 public int asyncMessageCount() {
145 if (getAsyncMessages() != null)
146 return getAsyncMessages().size();
152 * Returns the asyncMessage at the given index in the asyncMessage array
154 * @param index the position in the asyncMessage array
155 * @return the asyncMessage
157 public AsyncMessage
getAsyncMessage(int index
) {
158 if ((getAsyncMessages() != null) && (index
>= 0) && (index
< getAsyncMessages().size()))
159 return (AsyncMessage
) getAsyncMessages().get(index
);
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
167 * @return the syncMessages return list
169 protected List
<GraphNode
> getSyncMessagesReturn() {
173 return (List
<GraphNode
>) nodes
.get(SyncMessageReturn
.SYNC_MESS_RET_TAG
);
177 * Returns the number of syncMessageReturn stored in the frame
179 * @return the number of syncMessageReturn
181 public int syncMessageReturnCount() {
182 if (getSyncMessagesReturn() != null)
183 return getSyncMessagesReturn().size();
189 * Returns the syncMessageReturn at the given index in the syncMessageReturn array
191 * @param index the position in the syncMessageReturn array
192 * @return the syncMessageReturn
194 public SyncMessageReturn
getSyncMessageReturn(int index
) {
195 if ((getSyncMessagesReturn() != null) && (index
>= 0) && (index
< getSyncMessagesReturn().size()))
196 return (SyncMessageReturn
) getSyncMessagesReturn().get(index
);
201 * Returns a list of asyncMessageRetun known by this frame. Known asyncMessageRetun are the only on which can be
202 * displayed on screen
204 * @return the asyncMessageRetun list
206 protected List
<GraphNode
> getAsyncMessagesReturn() {
210 return (List
<GraphNode
>) nodes
.get(AsyncMessageReturn
.ASYNC_MESS_RET_TAG
);
214 * Returns the number of asyncMessageReturn stored in the frame
216 * @return the number of asyncMessageReturn
218 public int asyncMessageReturnCount() {
219 if (getAsyncMessagesReturn() != null)
220 return getAsyncMessagesReturn().size();
226 * Returns the asyncMessageReturn at the given index in the asyncMessageReturn array
228 * @param index the position in the asyncMessageReturn array
229 * @return the asyncMessageReturn
231 public AsyncMessageReturn
getAsyncMessageReturn(int index
) {
232 if ((getAsyncMessagesReturn() != null) && (index
>= 0) && (index
< getAsyncMessagesReturn().size()))
233 return (AsyncMessageReturn
) getAsyncMessagesReturn().get(index
);
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.
241 * @param the lifeline to add
243 public void addLifeLine(Lifeline lifeLine
) {
244 computeMinMax
= true;
245 if (lifeLine
== null)
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()) {
255 // add the lifeline to the lifelines list
260 * Returns the first visible lifeline drawn in the view
262 * @return the first visible lifeline index
264 public int getFirstVisibleLifeline() {
267 else if (indexes
.get(Lifeline
.LIFELINE_TAG
) != null)
268 return ((Integer
) indexes
.get(Lifeline
.LIFELINE_TAG
)).intValue();
274 * Returns the first visible synchronous message drawn in the view
276 * @return the first visible synchronous message index
278 public int getFirstVisibleSyncMessage() {
281 else if (indexes
.get(SyncMessage
.SYNC_MESS_TAG
) != null)
282 return ((Integer
) indexes
.get(SyncMessage
.SYNC_MESS_TAG
)).intValue();
288 * Returns the first visible synchronous message return drawn in the view
290 * @return the first visible synchronous message return index
292 public int getFirstVisibleSyncMessageReturn() {
295 else if (indexes
.get(SyncMessageReturn
.SYNC_MESS_RET_TAG
) != null)
296 return ((Integer
) indexes
.get(SyncMessageReturn
.SYNC_MESS_RET_TAG
)).intValue();
302 * Returns the first visible synchronous message drawn in the view
304 * @return the first visible synchronous message index
306 public int getFirstVisibleAsyncMessage() {
309 else if (indexes
.get(AsyncMessage
.ASYNC_MESS_TAG
) != null)
310 return ((Integer
) indexes
.get(AsyncMessage
.ASYNC_MESS_TAG
)).intValue();
316 * Returns the first visible synchronous message return drawn in the view
318 * @return the first visible synchronous message return index
320 public int getFirstVisibleAsyncMessageReturn() {
323 else if (indexes
.get(AsyncMessageReturn
.ASYNC_MESS_RET_TAG
) != null)
324 return ((Integer
) indexes
.get(AsyncMessageReturn
.ASYNC_MESS_RET_TAG
)).intValue();
329 public List
<SDTimeEvent
> getExecutionOccurrencesWithTime() {
330 return executionOccurrencesWithTime
;
333 public void insertLifelineAfter(Lifeline toInsert
, Lifeline after
) {
334 if ((toInsert
== null))
336 if (toInsert
== after
)
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
);
348 if (removePoint
>= insertPoint
)
349 toInsert
.setIndex(insertPoint
+ 1);
351 toInsert
.setIndex(insertPoint
- 1);
354 if (removePoint
>= insertPoint
) {
355 for (int i
= insertPoint
; i
< getLifelines().size(); i
++) {
356 getLifeline(i
).setIndex(i
+ 1);
359 for (int i
= 0; i
< insertPoint
&& i
< getLifelines().size(); i
++) {
360 getLifeline(i
).setIndex(i
+ 1);
365 public void insertLifelineBefore(Lifeline toInsert
, Lifeline before
) {
366 if ((toInsert
== null))
368 if (toInsert
== before
)
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
);
380 if (removePoint
>= insertPoint
)
381 toInsert
.setIndex(insertPoint
+ 1);
383 toInsert
.setIndex(insertPoint
- 1);
386 if (removePoint
>= insertPoint
) {
387 for (int i
= insertPoint
; i
< getLifelines().size(); i
++) {
388 getLifeline(i
).setIndex(i
+ 1);
391 for (int i
= 0; i
< insertPoint
&& i
< getLifelines().size(); i
++) {
392 getLifeline(i
).setIndex(i
+ 1);
397 public Lifeline
getCloserLifeline(int x
) {
398 int index
= (x
- Metrics
.FRAME_H_MARGIN
+ Metrics
.LIFELINE_H_MAGIN
) / Metrics
.swimmingLaneWidth() - 1;
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
);
408 node2
= getLifeline(index
- 1);
409 dist2
= Math
.abs(node2
.getX() + node2
.getWidth() / 2 - x
);
411 if (index
< getLifelines().size() - 1) {
412 node3
= getLifeline(index
+ 1);
413 dist3
= Math
.abs(node3
.getX() + node3
.getWidth() / 2 - x
);
415 if (dist1
<= dist2
&& dist1
<= dist3
)
417 else if (dist2
<= dist1
&& dist2
<= dist3
)
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));
431 insertLifelineBefore(temp
[0], temp
[1]);
437 public void resetTimeCompression() {
438 highlightLifeline
= null;
441 highlightColor
= null;
445 protected void computeMinMax() {
446 List
<SDTimeEvent
> timeArray
= buildTimeArray();
447 if (timeArray
== null)
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))
460 updateMinMax(m1
, m2
);
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.
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
473 public boolean findDateBounds(TmfTimestamp dateToFind
, ITimeRange bounds
[]) {
475 List
<SDTimeEvent
> timeArray
= buildTimeArray();
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();
483 bounds
[0] = ((SDTimeEvent
) timeArray
.get(i
- 1)).getGraphNode();
489 bounds
[0] = ((SDTimeEvent
) timeArray
.get(timeArray
.size() - 1)).getGraphNode();
494 protected void setHasTimeInfo(boolean value
) {
499 * @return true if frame has time info else false
501 public boolean hasTimeInfo() {
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
;
519 * Set the lifeline categories which will be use during the lifelines creation
521 * @see Lifeline#setCategory(int)
522 * @param categories the lifeline categories array
524 public void setLifelineCategories(LifelineCategories
[] categories
) {
525 lifelineCategories
= Arrays
.copyOf(categories
, categories
.length
);
529 * Returns the lifeline categories array set for the this frame
531 * @return the lifeline categories array or null if not set
533 public LifelineCategories
[] getLifelineCategories() {
534 return Arrays
.copyOf(lifelineCategories
, lifelineCategories
.length
);
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.
546 * @param the message to add
548 public void addMessage(BaseMessage message
) {
553 public void draw(IGC context
) {
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
);
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)
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())
576 toDraw
.drawName(context
);
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()))) {
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());
594 tempEvent
= tempEvent
+ 1;
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())
607 protected List
<SDTimeEvent
> buildTimeArray() {
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
);
626 if (executionOccurrencesWithTime
== null) {
627 executionOccurrencesWithTime
= new ArrayList
<SDTimeEvent
>();
629 executionOccurrencesWithTime
.add(f
);
630 event
= eo
.getEndOccurrence();
631 time
= eo
.getEndTime();
632 f
= new SDTimeEvent(time
, event
, eo
);
634 executionOccurrencesWithTime
.add(f
);
641 if (executionOccurrencesWithTime
!= null) {
642 SDTimeEvent
[] temp
= executionOccurrencesWithTime
.toArray(new SDTimeEvent
[0]);
643 Arrays
.sort(temp
, new TimeEventComparator());
644 executionOccurrencesWithTime
= Arrays
.asList(temp
);
646 SDTimeEvent
[] temp
= timeArray
.toArray(new SDTimeEvent
[0]);
647 Arrays
.sort(temp
, new TimeEventComparator());
648 timeArray
= Arrays
.asList(temp
);
650 } catch (Exception e
) {
657 protected GraphNode
getCloserLeavingMessage(Lifeline lifeline
, BaseMessage message
, List
<GraphNode
> list
, boolean smallerEvent
) {
660 if (smallerEvent
== false) {
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
))
670 } else if (node
instanceof AsyncMessage
) {
671 AsyncMessage asyncNode
= (AsyncMessage
) node
;
672 if ((asyncNode
.getStartOccurrence() > event
) && (asyncNode
.getStartLifeline() == lifeline
) && !asyncNode
.isSameAs(message
))
677 int event
= getMaxEventOccurrence();
679 if (message
instanceof AsyncMessage
) {
680 event
= ((AsyncMessage
) message
).getStartOccurrence();
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
))
689 } else if (node
instanceof AsyncMessage
) {
690 AsyncMessage asyncNode
= (AsyncMessage
) node
;
691 if ((asyncNode
.getStartOccurrence() < event
) && (asyncNode
.getStartLifeline() == lifeline
) && !asyncNode
.isSameAs(message
))
699 protected GraphNode
getCloserEnteringMessage(Lifeline lifeline
, BaseMessage message
, List
<GraphNode
> list
, boolean smallerEvent
) {
702 if (smallerEvent
== false) {
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
))
712 } else if (node
instanceof AsyncMessage
) {
713 AsyncMessage asyncNode
= (AsyncMessage
) node
;
714 if ((asyncNode
.getStartOccurrence() > event
) && (asyncNode
.getEndLifeline() == lifeline
) && !asyncNode
.isSameAs(message
))
719 int event
= getMaxEventOccurrence();
721 if (message
instanceof AsyncMessage
) {
722 event
= ((AsyncMessage
) message
).getStartOccurrence();
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
))
731 } else if (node
instanceof AsyncMessage
) {
732 AsyncMessage asyncNode
= (AsyncMessage
) node
;
733 if ((asyncNode
.getStartOccurrence() < event
) && (asyncNode
.getEndLifeline() == lifeline
) && !asyncNode
.isSameAs(message
))
741 protected int distanceFromEvent(GraphNode node
, int event
) {
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
;
751 distance
= end
- event
;
753 return Math
.abs(distance
);
756 protected GraphNode
getCloserToEvent(GraphNode node1
, GraphNode node2
, int event
) {
757 if ((node1
!= null) && (node2
!= null)) {
758 if (distanceFromEvent(node1
, event
) < distanceFromEvent(node2
, event
))
762 } else if (node1
!= null)
764 else if (node2
!= null)
770 public GraphNode
getCalledMessage(BaseMessage StartMessage
) {
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();
780 if (lifeline
== 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
);
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();
802 if (lifeline
== 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
);
814 public GraphNode
getNextLifelineMessage(Lifeline lifeline
, BaseMessage StartMessage
) {
816 if (StartMessage
!= null)
817 event
= ((BaseMessage
) StartMessage
).getEventOccurrence();
818 if (lifeline
== 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
);
830 public BasicExecutionOccurrence
getFirstExecution(Lifeline lifeline
) {
831 if (lifeline
== null)
833 List
<GraphNode
> list
= lifeline
.getExecutions();
836 if (list
.size() == 0)
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()))
847 public BasicExecutionOccurrence
getPrevExecOccurrence(BasicExecutionOccurrence exec
) {
850 Lifeline lifeline
= exec
.getLifeline();
851 if (lifeline
== null)
853 List
<GraphNode
> list
= lifeline
.getExecutions();
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))
861 if ((e
.getStartOccurrence() < exec
.startEventOccurrence
) && (e
.getStartOccurrence() >= result
.getEndOccurrence()))
867 public BasicExecutionOccurrence
getNextExecOccurrence(BasicExecutionOccurrence exec
) {
870 Lifeline lifeline
= exec
.getLifeline();
871 if (lifeline
== null)
873 List
<GraphNode
> list
= lifeline
.getExecutions();
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))
881 if ((e
.getStartOccurrence() > exec
.startEventOccurrence
) && (e
.getStartOccurrence() <= result
.getEndOccurrence()))
887 public BasicExecutionOccurrence
getLastExecOccurrence(Lifeline lifeline
) {
888 if (lifeline
== null)
890 List
<GraphNode
> list
= lifeline
.getExecutions();
893 BasicExecutionOccurrence result
= null;
894 for (int i
= 0; i
< list
.size(); i
++) {
895 BasicExecutionOccurrence e
= (BasicExecutionOccurrence
) list
.get(i
);
898 if (e
.getStartOccurrence() > result
.getEndOccurrence())
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();
910 event
= StartMessage
.getEventOccurrence();
911 if (lifeline
== 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
);