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
.ui
.views
.uml2sd
.drawings
.IColor
;
22 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.drawings
.IGC
;
23 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.preferences
.SDViewPref
;
24 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.util
.TimeEventComparator
;
27 * The Frame class is the base sequence diagram graph nodes container.<br>
28 * For instance, only one frame can be drawn in the View.<br>
29 * Lifelines, Messages and Stop which are supposed to represent a Sequence diagram are drawn in a Frame.<br>
30 * Only the graph node added to their representing list will be drawn.
32 * The lifelines are appended along the X axsis when added in a frame.<br>
33 * The syncMessages are ordered along the Y axsis depending on the event occurrence they are attached to.<br>
35 * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.Lifeline Lifeline for more event occurence details
39 public class Frame
extends BasicFrame
{
41 protected Lifeline highlightLifeline
= null;
42 protected int startEvent
= 0;
43 protected int nbEvent
= 0;
44 protected IColor highlightColor
= null;
46 protected List
<SDTimeEvent
> executionOccurrencesWithTime
;
48 protected LifelineCategories
[] lifelineCategories
= null;
51 * Returns a list of all lifelines known by this frame. Known lifelines are the only one which can be displayed on
54 * @return the lifelines list
56 protected List
<GraphNode
> getLifelines() {
60 return (List
<GraphNode
>) nodes
.get(Lifeline
.LIFELINE_TAG
);
64 * Returns the number of lifelines stored in the frame
66 * @return the number of lifelines
68 public int lifeLinesCount() {
69 List
<GraphNode
> lifelines
= getLifelines();
70 if (lifelines
!= null)
71 return lifelines
.size();
77 * Returns the lifeline at the given index in the lifelines array
79 * @param index the position in the lifeline array
80 * @return the lifeline
82 public Lifeline
getLifeline(int index
) {
83 if ((getLifelines() != null) && (index
>= 0) && (index
< lifeLinesCount()))
84 return (Lifeline
) getLifelines().get(index
);
89 * Returns a list of syncMessages known by this frame. Known syncMessages are the only on which can be displayed on
92 * @return the syncMessages list
94 protected List
<GraphNode
> getSyncMessages() {
98 return (List
<GraphNode
>) nodes
.get(SyncMessage
.SYNC_MESS_TAG
);
102 * Returns the number of syncMessages stored in the frame
104 * @return the number of syncMessage
106 public int syncMessageCount() {
107 if (getSyncMessages() != null)
108 return getSyncMessages().size();
114 * Returns the syncMessage at the given index in the syncMessages array
116 * @param index the position in the syncMessages array
117 * @return the syncMessage
119 public SyncMessage
getSyncMessage(int index
) {
120 if ((getSyncMessages() != null) && (index
>= 0) && (index
< getSyncMessages().size()))
121 return (SyncMessage
) getSyncMessages().get(index
);
126 * Returns a list of asyncMessages known by this frame. Known asyncMessages are the only on which can be displayed
129 * @return the asyncMessages list
131 protected List
<GraphNode
> getAsyncMessages() {
135 return (List
<GraphNode
>) nodes
.get(AsyncMessage
.ASYNC_MESS_TAG
);
139 * Returns the number of asyncMessage stored in the frame
141 * @return the number of asyncMessage
143 public int asyncMessageCount() {
144 if (getAsyncMessages() != null)
145 return getAsyncMessages().size();
151 * Returns the asyncMessage at the given index in the asyncMessage array
153 * @param index the position in the asyncMessage array
154 * @return the asyncMessage
156 public AsyncMessage
getAsyncMessage(int index
) {
157 if ((getAsyncMessages() != null) && (index
>= 0) && (index
< getAsyncMessages().size()))
158 return (AsyncMessage
) getAsyncMessages().get(index
);
163 * Returns a list of syncMessages return known by this frame. Known syncMessages return are the only on which can be
164 * displayed on screen
166 * @return the syncMessages return list
168 protected List
<GraphNode
> getSyncMessagesReturn() {
172 return (List
<GraphNode
>) nodes
.get(SyncMessageReturn
.SYNC_MESS_RET_TAG
);
176 * Returns the number of syncMessageReturn stored in the frame
178 * @return the number of syncMessageReturn
180 public int syncMessageReturnCount() {
181 if (getSyncMessagesReturn() != null)
182 return getSyncMessagesReturn().size();
188 * Returns the syncMessageReturn at the given index in the syncMessageReturn array
190 * @param index the position in the syncMessageReturn array
191 * @return the syncMessageReturn
193 public SyncMessageReturn
getSyncMessageReturn(int index
) {
194 if ((getSyncMessagesReturn() != null) && (index
>= 0) && (index
< getSyncMessagesReturn().size()))
195 return (SyncMessageReturn
) getSyncMessagesReturn().get(index
);
200 * Returns a list of asyncMessageRetun known by this frame. Known asyncMessageRetun are the only on which can be
201 * displayed on screen
203 * @return the asyncMessageRetun list
205 protected List
<GraphNode
> getAsyncMessagesReturn() {
209 return (List
<GraphNode
>) nodes
.get(AsyncMessageReturn
.ASYNC_MESS_RET_TAG
);
213 * Returns the number of asyncMessageReturn stored in the frame
215 * @return the number of asyncMessageReturn
217 public int asyncMessageReturnCount() {
218 if (getAsyncMessagesReturn() != null)
219 return getAsyncMessagesReturn().size();
225 * Returns the asyncMessageReturn at the given index in the asyncMessageReturn array
227 * @param index the position in the asyncMessageReturn array
228 * @return the asyncMessageReturn
230 public AsyncMessageReturn
getAsyncMessageReturn(int index
) {
231 if ((getAsyncMessagesReturn() != null) && (index
>= 0) && (index
< getAsyncMessagesReturn().size()))
232 return (AsyncMessageReturn
) getAsyncMessagesReturn().get(index
);
237 * Adds a lifeline to the frame lifelines list. The lifeline X drawing order depends on the lifeline addition order
238 * into the frame lifelines list.
240 * @param lifeline the lifeline to add
242 public void addLifeLine(Lifeline lifeline
) {
243 computeMinMax
= true;
244 if (lifeline
== null)
246 // set the lifeline parent frame
247 lifeline
.setFrame(this);
248 // Increate the frame lifeline counter
249 // and set the lifeline drawing order
250 lifeline
.setIndex(getNewHorizontalIndex());
251 if (lifeline
.hasTimeInfo()) {
254 // add the lifeline to the lifelines list
259 * Returns the first visible lifeline drawn in the view
261 * @return the first visible lifeline index
263 public int getFirstVisibleLifeline() {
266 else if (indexes
.get(Lifeline
.LIFELINE_TAG
) != null)
267 return ((Integer
) indexes
.get(Lifeline
.LIFELINE_TAG
)).intValue();
273 * Returns the first visible synchronous message drawn in the view
275 * @return the first visible synchronous message index
277 public int getFirstVisibleSyncMessage() {
280 else if (indexes
.get(SyncMessage
.SYNC_MESS_TAG
) != null)
281 return ((Integer
) indexes
.get(SyncMessage
.SYNC_MESS_TAG
)).intValue();
287 * Returns the first visible synchronous message return drawn in the view
289 * @return the first visible synchronous message return index
291 public int getFirstVisibleSyncMessageReturn() {
294 else if (indexes
.get(SyncMessageReturn
.SYNC_MESS_RET_TAG
) != null)
295 return ((Integer
) indexes
.get(SyncMessageReturn
.SYNC_MESS_RET_TAG
)).intValue();
301 * Returns the first visible synchronous message drawn in the view
303 * @return the first visible synchronous message index
305 public int getFirstVisibleAsyncMessage() {
308 else if (indexes
.get(AsyncMessage
.ASYNC_MESS_TAG
) != null)
309 return ((Integer
) indexes
.get(AsyncMessage
.ASYNC_MESS_TAG
)).intValue();
315 * Returns the first visible synchronous message return drawn in the view
317 * @return the first visible synchronous message return index
319 public int getFirstVisibleAsyncMessageReturn() {
322 else if (indexes
.get(AsyncMessageReturn
.ASYNC_MESS_RET_TAG
) != null)
323 return ((Integer
) indexes
.get(AsyncMessageReturn
.ASYNC_MESS_RET_TAG
)).intValue();
328 public List
<SDTimeEvent
> getExecutionOccurrencesWithTime() {
329 return executionOccurrencesWithTime
;
332 public void insertLifelineAfter(Lifeline toInsert
, Lifeline after
) {
333 if ((toInsert
== null))
335 if (toInsert
== after
)
339 insertPoint
= after
.getIndex();
340 int removePoint
= toInsert
.getIndex() - 1;
341 if (removePoint
>= insertPoint
)
342 getLifelines().remove(removePoint
);
343 getLifelines().add(insertPoint
, toInsert
);
344 if (removePoint
< insertPoint
)
345 getLifelines().remove(removePoint
);
347 if (removePoint
>= insertPoint
)
348 toInsert
.setIndex(insertPoint
+ 1);
350 toInsert
.setIndex(insertPoint
- 1);
353 if (removePoint
>= insertPoint
) {
354 for (int i
= insertPoint
; i
< getLifelines().size(); i
++) {
355 getLifeline(i
).setIndex(i
+ 1);
358 for (int i
= 0; i
< insertPoint
&& i
< getLifelines().size(); i
++) {
359 getLifeline(i
).setIndex(i
+ 1);
364 public void insertLifelineBefore(Lifeline toInsert
, Lifeline before
) {
365 if ((toInsert
== null))
367 if (toInsert
== before
)
371 insertPoint
= before
.getIndex() - 1;
372 int removePoint
= toInsert
.getIndex() - 1;
373 if (removePoint
>= insertPoint
)
374 getLifelines().remove(removePoint
);
375 getLifelines().add(insertPoint
, toInsert
);
376 if (removePoint
< insertPoint
)
377 getLifelines().remove(removePoint
);
379 if (removePoint
>= insertPoint
)
380 toInsert
.setIndex(insertPoint
+ 1);
382 toInsert
.setIndex(insertPoint
- 1);
385 if (removePoint
>= insertPoint
) {
386 for (int i
= insertPoint
; i
< getLifelines().size(); i
++) {
387 getLifeline(i
).setIndex(i
+ 1);
390 for (int i
= 0; i
< insertPoint
&& i
< getLifelines().size(); i
++) {
391 getLifeline(i
).setIndex(i
+ 1);
396 public Lifeline
getCloserLifeline(int x
) {
397 int index
= (x
- Metrics
.FRAME_H_MARGIN
+ Metrics
.LIFELINE_H_MAGIN
) / Metrics
.swimmingLaneWidth() - 1;
400 if (index
>= getLifelines().size())
401 index
= getLifelines().size() - 1;
402 Lifeline node1
, node2
, node3
;
403 int dist1
, dist2
, dist3
;
404 node1
= node2
= node3
= getLifeline(index
);
405 dist1
= dist2
= dist3
= Math
.abs(node1
.getX() + node1
.getWidth() / 2 - x
);
407 node2
= getLifeline(index
- 1);
408 dist2
= Math
.abs(node2
.getX() + node2
.getWidth() / 2 - x
);
410 if (index
< getLifelines().size() - 1) {
411 node3
= getLifeline(index
+ 1);
412 dist3
= Math
.abs(node3
.getX() + node3
.getWidth() / 2 - x
);
414 if (dist1
<= dist2
&& dist1
<= dist3
)
416 else if (dist2
<= dist1
&& dist2
<= dist3
)
422 public void reorder(ArrayList
<?
> list
) {
423 for (int i
= 0; i
< list
.size(); i
++) {
424 if (list
.get(i
) instanceof Lifeline
[]) {
425 Lifeline temp
[] = (Lifeline
[]) list
.get(i
);
426 if (temp
.length
== 2) {
427 if (temp
[1] == null) {
428 insertLifelineAfter(temp
[0], getLifeline(lifeLinesCount() - 1));
430 insertLifelineBefore(temp
[0], temp
[1]);
436 public void resetTimeCompression() {
437 highlightLifeline
= null;
440 highlightColor
= null;
444 protected void computeMinMax() {
445 List
<SDTimeEvent
> timeArray
= buildTimeArray();
446 if (timeArray
== null)
448 for (int i
= 0; i
< timeArray
.size() - 1; i
++) {
449 SDTimeEvent m1
= (SDTimeEvent
) timeArray
.get(i
);
450 SDTimeEvent m2
= (SDTimeEvent
) timeArray
.get(i
+ 1);
451 if (SDViewPref
.getInstance().excludeExternalTime())
452 if ((m1
.getGraphNode() instanceof BaseMessage
) && (m2
.getGraphNode() instanceof BaseMessage
)) {
453 BaseMessage mes1
= (BaseMessage
) m1
.getGraphNode();
454 BaseMessage mes2
= (BaseMessage
) m2
.getGraphNode();
455 if ((mes2
.startLifeline
== null) || (mes1
.endLifeline
== null))
459 updateMinMax(m1
, m2
);
464 * Find the two graph nodes that are closest to this date, one just earlier, second just later. If date is before
465 * any graph node, bounds[0] is null and bounds[1] is the earliest. If date is after any graph node, bounds[1] is
466 * null and bounds[0] is the latest.
468 * @param dateToFind date to be found
469 * @param bounds a two items array that will receive bounds if found
470 * @return true if both bounds not null
472 public boolean findDateBounds(ITmfTimestamp dateToFind
, ITimeRange bounds
[]) {
474 List
<SDTimeEvent
> timeArray
= buildTimeArray();
477 for (int i
= 0; i
< timeArray
.size(); i
++) {
478 SDTimeEvent m
= (SDTimeEvent
) timeArray
.get(i
);
479 if (m
.getTime().compareTo(dateToFind
, true) > 0) {
480 bounds
[1] = m
.getGraphNode();
482 bounds
[0] = ((SDTimeEvent
) timeArray
.get(i
- 1)).getGraphNode();
488 bounds
[0] = ((SDTimeEvent
) timeArray
.get(timeArray
.size() - 1)).getGraphNode();
493 protected void setHasTimeInfo(boolean value
) {
498 * @return true if frame has time info else false
500 public boolean hasTimeInfo() {
510 public void highlightTimeCompression(Lifeline lifeline
, int startEvent
, int nbEvent
, IColor color
) {
511 highlightLifeline
= lifeline
;
512 this.startEvent
= startEvent
;
513 this.nbEvent
= nbEvent
;
514 highlightColor
= color
;
518 * Set the lifeline categories which will be use during the lifelines creation
520 * @see Lifeline#setCategory(int)
521 * @param categories the lifeline categories array
523 public void setLifelineCategories(LifelineCategories
[] categories
) {
524 lifelineCategories
= Arrays
.copyOf(categories
, categories
.length
);
528 * Returns the lifeline categories array set for the this frame
530 * @return the lifeline categories array or null if not set
532 public LifelineCategories
[] getLifelineCategories() {
533 return Arrays
.copyOf(lifelineCategories
, lifelineCategories
.length
);
537 * Adds a message to the Frame message list. Four kinds of syncMessages can be added:<br>
538 * - synchronous syncMessages<br>
539 * - synchronous syncMessages return<br>
540 * - asynchronous syncMessages<br>
541 * - asynchronous syncMessages return<br>
542 * For drawing performance reason, it is recommended to add synchronous syncMessages in the same order they should
543 * appear along the Y axis in the Frame.
545 * @param message the message to add
547 public void addMessage(BaseMessage message
) {
552 public void draw(IGC context
) {
557 if (highlightLifeline
!= null) {
558 IColor backupColor
= context
.getBackground();
559 context
.setBackground(Frame
.getUserPref().getTimeCompressionSelectionColor());
560 int gy
= highlightLifeline
.getY() + highlightLifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * startEvent
;
561 context
.fillRectangle(Metrics
.FRAME_H_MARGIN
+ 1, gy
, highlightLifeline
.getX() + Metrics
.getLifelineWidth() / 2 - Metrics
.FRAME_H_MARGIN
, (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * nbEvent
);
562 context
.setBackground(backupColor
);
564 super.draw(context
, false);
565 int lifelineArryStep
= 1;
566 if (Metrics
.swimmingLaneWidth() * context
.getZoom() < Metrics
.LIFELINE_SIGNIFICANT_HSPACING
)
567 lifelineArryStep
= Math
.round(Metrics
.LIFELINE_SIGNIFICANT_HSPACING
/ (Metrics
.swimmingLaneWidth() * context
.getZoom()));
568 if (indexes
.size() == 0)
570 int lifeLineDrawIndex
= ((Integer
) indexes
.get(Lifeline
.LIFELINE_TAG
)).intValue();
571 for (int i
= lifeLineDrawIndex
; i
< ((List
<GraphNode
>) nodes
.get(Lifeline
.LIFELINE_TAG
)).size(); i
= i
+ lifelineArryStep
) {
572 Lifeline toDraw
= (Lifeline
) ((List
<GraphNode
>) nodes
.get(Lifeline
.LIFELINE_TAG
)).get(i
);
573 if (toDraw
.getX() - Metrics
.LIFELINE_SPACING
/ 2 > context
.getContentsX() + context
.getVisibleWidth())
575 toDraw
.drawName(context
);
577 if (highlightLifeline
!= null) {
578 if (toDraw
== highlightLifeline
)
579 toDraw
.highlightExecOccurrenceRegion(context
, startEvent
, nbEvent
, highlightColor
);
580 else if ((toDraw
.getIndex() < highlightLifeline
.getIndex()) || ((toDraw
.getIndex() < highlightLifeline
.getIndex()))) {
582 int acIndex
= toDraw
.getExecOccurrenceDrawIndex();
583 // acIndex = first visible execution occurrence
584 // for drawing speed reason with only search on the visible subset
585 if (toDraw
.getExecutions() != null)
586 for (int index
= acIndex
; index
< toDraw
.getExecutions().size(); index
++) {
587 BasicExecutionOccurrence exec
= (BasicExecutionOccurrence
) toDraw
.getExecutions().get(index
);
588 int tempEvent
= startEvent
;
589 for (int j
= 0; j
< nbEvent
; j
++) {
590 if (((tempEvent
>= exec
.startEventOccurrence
) && (tempEvent
<= exec
.endEventOccurrence
) && (tempEvent
+ 1 >= exec
.startEventOccurrence
) && (tempEvent
+ 1 <= exec
.endEventOccurrence
))) {
591 toDraw
.highlightExecOccurrenceRegion(context
, tempEvent
, 1, Frame
.getUserPref().getTimeCompressionSelectionColor());
593 tempEvent
= tempEvent
+ 1;
595 // if we are outside the visible area we stop right now
596 // This works because execution occurrences are ordered along the Y axis
597 if (exec
.getY() > getY())
606 protected List
<SDTimeEvent
> buildTimeArray() {
610 List
<SDTimeEvent
> timeArray
= super.buildTimeArray();
611 executionOccurrencesWithTime
= null;
612 if (getLifelines() != null)
613 for (int i
= 0; i
< ((List
<GraphNode
>) nodes
.get(Lifeline
.LIFELINE_TAG
)).size(); i
++) {
614 Lifeline l
= (Lifeline
) ((List
<GraphNode
>) nodes
.get(Lifeline
.LIFELINE_TAG
)).get(i
);
615 if (l
.hasTimeInfo() && l
.getExecutions() != null) {
616 for (Iterator
<GraphNode
> j
= l
.getExecutions().iterator(); j
.hasNext();) {
617 GraphNode o
= j
.next();
618 if (o
instanceof ExecutionOccurrence
) {
619 ExecutionOccurrence eo
= (ExecutionOccurrence
) o
;
620 if (eo
.hasTimeInfo()) {
621 int event
= eo
.getStartOccurrence();
622 ITmfTimestamp time
= eo
.getStartTime();
623 SDTimeEvent f
= new SDTimeEvent(time
, event
, eo
);
625 if (executionOccurrencesWithTime
== null) {
626 executionOccurrencesWithTime
= new ArrayList
<SDTimeEvent
>();
628 executionOccurrencesWithTime
.add(f
);
629 event
= eo
.getEndOccurrence();
630 time
= eo
.getEndTime();
631 f
= new SDTimeEvent(time
, event
, eo
);
633 executionOccurrencesWithTime
.add(f
);
640 if (executionOccurrencesWithTime
!= null) {
641 SDTimeEvent
[] temp
= executionOccurrencesWithTime
.toArray(new SDTimeEvent
[0]);
642 Arrays
.sort(temp
, new TimeEventComparator());
643 executionOccurrencesWithTime
= Arrays
.asList(temp
);
645 SDTimeEvent
[] temp
= timeArray
.toArray(new SDTimeEvent
[0]);
646 Arrays
.sort(temp
, new TimeEventComparator());
647 timeArray
= Arrays
.asList(temp
);
649 } catch (Exception e
) {
656 protected GraphNode
getCloserLeavingMessage(Lifeline lifeline
, BaseMessage message
, List
<GraphNode
> list
, boolean smallerEvent
) {
659 if (smallerEvent
== false) {
662 event
= message
.getEventOccurrence();
663 for (int i
= 0; i
< list
.size(); i
++) {
664 GraphNode node
= (GraphNode
) list
.get(i
);
665 if (node
instanceof SyncMessage
) {
666 SyncMessage syncNode
= (SyncMessage
) node
;
667 if ((syncNode
.getEventOccurrence() > event
) && (syncNode
.getStartLifeline() == lifeline
) && !syncNode
.isSameAs(message
))
669 } else if (node
instanceof AsyncMessage
) {
670 AsyncMessage asyncNode
= (AsyncMessage
) node
;
671 if ((asyncNode
.getStartOccurrence() > event
) && (asyncNode
.getStartLifeline() == lifeline
) && !asyncNode
.isSameAs(message
))
676 int event
= getMaxEventOccurrence();
678 if (message
instanceof AsyncMessage
) {
679 event
= ((AsyncMessage
) message
).getStartOccurrence();
681 event
= message
.getEventOccurrence();
682 for (int i
= list
.size() - 1; i
>= 0; i
--) {
683 GraphNode node
= (GraphNode
) list
.get(i
);
684 if (node
instanceof SyncMessage
) {
685 SyncMessage syncNode
= (SyncMessage
) node
;
686 if ((syncNode
.getEventOccurrence() < event
) && (syncNode
.getStartLifeline() == lifeline
) && !syncNode
.isSameAs(message
))
688 } else if (node
instanceof AsyncMessage
) {
689 AsyncMessage asyncNode
= (AsyncMessage
) node
;
690 if ((asyncNode
.getStartOccurrence() < event
) && (asyncNode
.getStartLifeline() == lifeline
) && !asyncNode
.isSameAs(message
))
698 protected GraphNode
getCloserEnteringMessage(Lifeline lifeline
, BaseMessage message
, List
<GraphNode
> list
, boolean smallerEvent
) {
701 if (smallerEvent
== false) {
704 event
= message
.getEventOccurrence();
705 for (int i
= 0; i
< list
.size(); i
++) {
706 GraphNode node
= (GraphNode
) list
.get(i
);
707 if (node
instanceof SyncMessage
) {
708 SyncMessage syncNode
= (SyncMessage
) node
;
709 if ((syncNode
.getEventOccurrence() > event
) && (syncNode
.getEndLifeline() == lifeline
) && !syncNode
.isSameAs(message
))
711 } else if (node
instanceof AsyncMessage
) {
712 AsyncMessage asyncNode
= (AsyncMessage
) node
;
713 if ((asyncNode
.getStartOccurrence() > event
) && (asyncNode
.getEndLifeline() == lifeline
) && !asyncNode
.isSameAs(message
))
718 int event
= getMaxEventOccurrence();
720 if (message
instanceof AsyncMessage
) {
721 event
= ((AsyncMessage
) message
).getStartOccurrence();
723 event
= message
.getEventOccurrence();
724 for (int i
= list
.size() - 1; i
>= 0; i
--) {
725 GraphNode node
= (GraphNode
) list
.get(i
);
726 if (node
instanceof SyncMessage
) {
727 SyncMessage syncNode
= (SyncMessage
) node
;
728 if ((syncNode
.getEventOccurrence() < event
) && (syncNode
.getEndLifeline() == lifeline
) && !syncNode
.isSameAs(message
))
730 } else if (node
instanceof AsyncMessage
) {
731 AsyncMessage asyncNode
= (AsyncMessage
) node
;
732 if ((asyncNode
.getStartOccurrence() < event
) && (asyncNode
.getEndLifeline() == lifeline
) && !asyncNode
.isSameAs(message
))
740 protected int distanceFromEvent(GraphNode node
, int event
) {
742 if (node
instanceof SyncMessage
)
743 distance
= ((SyncMessage
) node
).getEventOccurrence() - event
;
744 else if (node
instanceof AsyncMessage
) {
745 int start
= ((AsyncMessage
) node
).getStartOccurrence();
746 int end
= ((AsyncMessage
) node
).getEndOccurrence();
747 if ((start
- event
) < (end
- event
))
748 distance
= start
- event
;
750 distance
= end
- event
;
752 return Math
.abs(distance
);
755 protected GraphNode
getCloserToEvent(GraphNode node1
, GraphNode node2
, int event
) {
756 if ((node1
!= null) && (node2
!= null)) {
757 if (distanceFromEvent(node1
, event
) < distanceFromEvent(node2
, event
))
761 } else if (node1
!= null)
763 else if (node2
!= null)
769 public GraphNode
getCalledMessage(BaseMessage StartMessage
) {
771 GraphNode result
= null;
772 Lifeline lifeline
= null;
773 if (StartMessage
!= null) {
774 event
= ((BaseMessage
) StartMessage
).getEventOccurrence();
775 lifeline
= ((BaseMessage
) StartMessage
).getEndLifeline();
776 if (lifeline
== null)
777 lifeline
= ((BaseMessage
) StartMessage
).getStartLifeline();
779 if (lifeline
== null)
781 GraphNode message
= getCloserLeavingMessage(lifeline
, StartMessage
, getSyncMessages(), false);
782 GraphNode messageReturn
= getCloserLeavingMessage(lifeline
, StartMessage
, getSyncMessagesReturn(), false);
783 result
= getCloserToEvent(message
, messageReturn
, event
);
784 message
= getCloserLeavingMessage(lifeline
, StartMessage
, getAsyncMessages(), false);
785 result
= getCloserToEvent(result
, message
, event
);
786 messageReturn
= getCloserLeavingMessage(lifeline
, StartMessage
, getAsyncMessagesReturn(), false);
787 result
= getCloserToEvent(result
, messageReturn
, event
);
791 public GraphNode
getCallerMessage(BaseMessage StartMessage
) {
792 int event
= getMaxEventOccurrence();
793 GraphNode result
= null;
794 Lifeline lifeline
= null;
795 if (StartMessage
!= null) {
796 event
= ((BaseMessage
) StartMessage
).getEventOccurrence();
797 lifeline
= ((BaseMessage
) StartMessage
).getStartLifeline();
798 if (lifeline
== null)
799 lifeline
= ((BaseMessage
) StartMessage
).getEndLifeline();
801 if (lifeline
== null)
803 GraphNode message
= getCloserEnteringMessage(lifeline
, StartMessage
, getSyncMessages(), true);
804 GraphNode messageReturn
= getCloserEnteringMessage(lifeline
, StartMessage
, getSyncMessagesReturn(), true);
805 result
= getCloserToEvent(message
, messageReturn
, event
);
806 message
= getCloserEnteringMessage(lifeline
, StartMessage
, getAsyncMessages(), true);
807 result
= getCloserToEvent(result
, message
, event
);
808 messageReturn
= getCloserEnteringMessage(lifeline
, StartMessage
, getAsyncMessagesReturn(), true);
809 result
= getCloserToEvent(result
, messageReturn
, event
);
813 public GraphNode
getNextLifelineMessage(Lifeline lifeline
, BaseMessage StartMessage
) {
815 if (StartMessage
!= null)
816 event
= ((BaseMessage
) StartMessage
).getEventOccurrence();
817 if (lifeline
== null)
819 GraphNode message
= getCloserLeavingMessage(lifeline
, StartMessage
, getSyncMessages(), false);
820 GraphNode messageReturn
= getCloserLeavingMessage(lifeline
, StartMessage
, getSyncMessagesReturn(), false);
821 GraphNode result
= getCloserToEvent(message
, messageReturn
, event
);
822 message
= getCloserLeavingMessage(lifeline
, StartMessage
, getAsyncMessages(), false);
823 result
= getCloserToEvent(result
, message
, event
);
824 messageReturn
= getCloserLeavingMessage(lifeline
, StartMessage
, getAsyncMessagesReturn(), false);
825 result
= getCloserToEvent(result
, messageReturn
, event
);
829 public BasicExecutionOccurrence
getFirstExecution(Lifeline lifeline
) {
830 if (lifeline
== null)
832 List
<GraphNode
> list
= lifeline
.getExecutions();
835 if (list
.size() == 0)
837 BasicExecutionOccurrence result
= (BasicExecutionOccurrence
) list
.get(0);
838 for (int i
= 0; i
< list
.size(); i
++) {
839 BasicExecutionOccurrence e
= (BasicExecutionOccurrence
) list
.get(i
);
840 if ((e
.getStartOccurrence() < result
.getEndOccurrence()))
846 public BasicExecutionOccurrence
getPrevExecOccurrence(BasicExecutionOccurrence exec
) {
849 Lifeline lifeline
= exec
.getLifeline();
850 if (lifeline
== null)
852 List
<GraphNode
> list
= lifeline
.getExecutions();
855 BasicExecutionOccurrence result
= null;
856 for (int i
= 0; i
< list
.size(); i
++) {
857 BasicExecutionOccurrence e
= (BasicExecutionOccurrence
) list
.get(i
);
858 if ((e
.getStartOccurrence() < exec
.startEventOccurrence
) && (result
== null))
860 if ((e
.getStartOccurrence() < exec
.startEventOccurrence
) && (e
.getStartOccurrence() >= result
.getEndOccurrence()))
866 public BasicExecutionOccurrence
getNextExecOccurrence(BasicExecutionOccurrence exec
) {
869 Lifeline lifeline
= exec
.getLifeline();
870 if (lifeline
== null)
872 List
<GraphNode
> list
= lifeline
.getExecutions();
875 BasicExecutionOccurrence result
= null;
876 for (int i
= 0; i
< list
.size(); i
++) {
877 BasicExecutionOccurrence e
= (BasicExecutionOccurrence
) list
.get(i
);
878 if ((e
.getStartOccurrence() > exec
.startEventOccurrence
) && (result
== null))
880 if ((e
.getStartOccurrence() > exec
.startEventOccurrence
) && (e
.getStartOccurrence() <= result
.getEndOccurrence()))
886 public BasicExecutionOccurrence
getLastExecOccurrence(Lifeline lifeline
) {
887 if (lifeline
== null)
889 List
<GraphNode
> list
= lifeline
.getExecutions();
892 BasicExecutionOccurrence result
= null;
893 for (int i
= 0; i
< list
.size(); i
++) {
894 BasicExecutionOccurrence e
= (BasicExecutionOccurrence
) list
.get(i
);
897 if (e
.getStartOccurrence() > result
.getEndOccurrence())
903 public GraphNode
getPrevLifelineMessage(Lifeline lifeline
, BaseMessage StartMessage
) {
904 int event
= getMaxEventOccurrence();
905 if (StartMessage
!= null)
906 if (StartMessage
instanceof AsyncMessage
) {
907 event
= ((AsyncMessage
) StartMessage
).getStartOccurrence();
909 event
= StartMessage
.getEventOccurrence();
910 if (lifeline
== null)
912 GraphNode message
= getCloserLeavingMessage(lifeline
, StartMessage
, getSyncMessages(), true);
913 GraphNode messageReturn
= getCloserLeavingMessage(lifeline
, StartMessage
, getSyncMessagesReturn(), true);
914 GraphNode result
= getCloserToEvent(message
, messageReturn
, event
);
915 message
= getCloserLeavingMessage(lifeline
, StartMessage
, getAsyncMessages(), true);
916 result
= getCloserToEvent(result
, message
, event
);
917 messageReturn
= getCloserLeavingMessage(lifeline
, StartMessage
, getAsyncMessagesReturn(), true);
918 result
= getCloserToEvent(result
, messageReturn
, event
);