package org.eclipse.uml2.diagram.sequence.internal.layout.model;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import org.eclipse.uml2.diagram.sequence.internal.layout.abstractgde.AbsNode;
import org.eclipse.uml2.diagram.sequence.internal.layout.vertical.input.HorizontalConstraint;
import org.eclipse.uml2.diagram.sequence.internal.layout.vertical.input.LifeLine;
import org.eclipse.uml2.diagram.sequence.internal.layout.vertical.input.LifeLineElement;
import org.eclipse.uml2.diagram.sequence.internal.layout.vertical.input.OrderingConstraint;
/**
*
*/
public abstract class LMGenCallOccurence extends LMLifeLineBracket implements LMMessageEnd {
LMGenCallOccurence(AbsNode gdeBracketNode, BracketMetaObject bracketMetaObject, LmOwner lmOwner) {
super(gdeBracketNode, bracketMetaObject, lmOwner);
myTopLifeLineElement = new BoundaryLifeLineElement(new BracketTopPosition(), bracketMetaObject.getTopOutSpace(), bracketMetaObject.getTopOutSpace()+bracketMetaObject.getTopInSpace())
{
public HorizontalConstraint getHorizontalConstraint() {
if (myHorizontalConstraintCallMessage == null) {
return null;
} else {
HorizontalConstraint result = myHorizontalConstraintCallMessage.getTopHorizontalConstraint();
////assert
//if (!result.getLifeLineElementsList().contains(this)) {
// throw new RuntimeException("Cannot find myself in constrained elements");
//}
return result;
}
}
public int getSize() {
return getTopOutSpace() + getTopInSpace();
}
public int getPointOffset() {
return getTopOutSpace();
}
int getMessagesVerticalPosOffset() {
return 0;
}
public String toString() {
return getDebugId()+"-Top"; //$NON-NLS-1$
}
};
myBottomLifeLineElement = new BoundaryLifeLineElement(new BracketBottomPosition(), bracketMetaObject.getBottomInSpace(), bracketMetaObject.getBottomInSpace()+bracketMetaObject.getBottomOutSpace())
{
public HorizontalConstraint getHorizontalConstraint() {
if (myHorizontalConstraintCallMessage == null) {
return null;
} else {
HorizontalConstraint result = myHorizontalConstraintCallMessage.getBottomHorizontalConstraint();
////assert
//if (!result.getLifeLineElementsList().contains(this)) {
// throw new RuntimeException("Cannot find myself in constrained elements");
//}
return result;
}
}
protected void setPositionValue(int pos, boolean doNotReshapeMessages) {
if (hasNoDuration()) {
pos = myTopLifeLineElement.getPositionValue()+getBracketMetaObject().getTopInSpace() + getBracketMetaObject().getBottomInSpace();
}
super.setPositionValue(pos, doNotReshapeMessages);
}
public boolean isVirtual() {
return hasNoDuration() ;
}
int getMessagesVerticalPosOffset() {
return -1;
}
public String toString() {
return getDebugId()+"-Bottom"; //$NON-NLS-1$
}
};
}
LMLifeLineBracket getDestructionCandidate() {
return getDestructionCandidateInCallOccurence();
}
LMLifeLineBracket getDestructionCandidateInCallOccurence() {
if (getChildBracketsList().isEmpty()) {
return null;
}
List listView = getChildBracketsList().getListView();
LMLifeLineBracket lastBracket = (LMLifeLineBracket) listView.get(listView.size()-1);
return lastBracket.getDestructionCandidateInCallOccurence();
}
void setLifelineToProvideBottomPos(LMLifeLine lifeLine) {
myLifelineToProvideBottomPos = lifeLine;
}
public LMFrame getContainingFrame() {
return super.getContainingFrame();
}
LMGenCallOccurence getContainingCallOccurence() {
return this;
}
protected abstract String getDebugId();
protected int getTopOutSpace() {
return getBracketMetaObject().getTopOutSpace();
}
protected int getTopInSpace() {
return getBracketMetaObject().getTopInSpace();
}
public SDVerticalLayoutInputImpl.NullFreeIterator verticalLayoutElements() {
//// assert
//{
// assertChildBracketsInCorrectOrder();
//}
return new SDVerticalLayoutInputImpl.NullFreeIteratorForArray(5) {
protected Object get(int pos) {
switch (pos) {
case 0: return myTopLifeLineElement;
case 1: return getClueValue();
case 2: return new LMBracketContainer.ChildBracketsNFIterator();
case 3: return getClueValue();
case 4: return myBottomLifeLineElement;
}
throw new IndexOutOfBoundsException();
}
};
}
public boolean isLimitedHorizontally() {
return true;
}
protected void setBracketBottomPos(int pos) {
if (myLifelineToProvideBottomPos != null) {
myLifelineToProvideBottomPos.setLifeLineGdeBottomPos(pos);
}
super.setBracketBottomPos(pos);
}
public void addMessage(LMMessage lmMessage) {
if (isMessageTopNotBottom(lmMessage)) {
addTopMessage(lmMessage);
} else {
addBottomMessage(lmMessage);
}
}
public void removeMessage(LMMessage lmMessage) {
if (isMessageTopNotBottom(lmMessage)) {
removeTopMessage(lmMessage);
} else {
removeBottomMessage(lmMessage);
}
}
public void messageIsJustReshaped(LMMessage lmMessage, JustReshapedState justReshapedState) {
boolean sendNotReceive = lmMessage.getSendMessageEnd() == this;
boolean topNotBottom = isMessageTopNotBottom(lmMessage);
boolean sourceNotDestination = ! sendNotReceive ^ topNotBottom;
BoundaryLifeLineElement position;
if (topNotBottom) {
position = getTopBoundaryLifeLineElement();
} else {
position = getBottomBoundaryLifeLineElement();
}
int pos = lmMessage.getLMMessageEndVerticalPosition(sourceNotDestination);
position.setPositionValueFromMessage(pos);
setJustReshaped(justReshapedState);
}
public LmBracketsList getChildBracketsList() {
return myChildBracketsList;
}
protected boolean isMessageTopNotBottom(LMMessage lmMessage) {
return lmMessage.isFromSendToReceive();
}
public boolean hasNoDuration() {
return myChildBracketsList.isEmpty() && getBracketMetaObject().tieBottomToTop();
}
private void addTopMessage(LMMessage lmCallMessage) {
getTopBoundaryLifeLineElement().getLMMesssagesList().add(lmCallMessage);
}
private void addBottomMessage(LMMessage lmReturnMessage) {
getBottomBoundaryLifeLineElement().getLMMesssagesList().add(lmReturnMessage);
}
private void removeTopMessage(LMMessage lmCallMessage) {
if (myHorizontalConstraintCallMessage == lmCallMessage) {
throw new IllegalArgumentException("Cannot remove lmCallMessage, before it removed from constraints"); //$NON-NLS-1$
}
getTopBoundaryLifeLineElement().getLMMesssagesList().remove(lmCallMessage);
}
private void removeBottomMessage(LMMessage lmReturnMessage) {
getBottomBoundaryLifeLineElement().getLMMesssagesList().remove(lmReturnMessage);
}
List getToplMessagesList() {
return getTopBoundaryLifeLineElement().getLMMesssagesList();
}
public BoundaryLifeLineElement getBottomBoundaryLifeLineElement() {
return myBottomLifeLineElement;
}
public BoundaryLifeLineElement getTopBoundaryLifeLineElement() {
return myTopLifeLineElement;
}
protected int getBracketTopPos() {
int result = super.getBracketTopPos();
if (result == 0) {
for (Iterator it = getTopBoundaryLifeLineElement().getLMMesssagesList().iterator(); it.hasNext(); ) {
LMMessage lmMessage = (LMMessage) it.next();
boolean getGdeStartNotEnd = ! getLMMessageEndSourceNotDestination(lmMessage) ^ lmMessage.isFromSendToReceive();
Point [] points = lmMessage.getGdeLink().getLinkPoints();
if (points != null && points.length>0) {
int y;
if (getGdeStartNotEnd) {
y = points[0].y;
} else {
y = points[points.length-1].y;
}
if (y != 0) {
result = y;
break;
}
}
}
}
return result;
}
protected abstract boolean getLMMessageEndSourceNotDestination(LMMessage lmMessage);
protected void setLMMessageEndVerticalPosition(LMMessage lmMessage, int pos, int siblingNumber) {
boolean changeGdeStartNotEnd = ! getLMMessageEndSourceNotDestination(lmMessage) ^ lmMessage.isFromSendToReceive();
lmMessage.setLMMessageEndVerticalPosition(pos, changeGdeStartNotEnd, siblingNumber);
}
public void setHorizontalPosition(int newPos) {
}
protected abstract class BoundaryLifeLineElement extends SDVerticalLayoutInputImpl.LifeLineElementSizeAdapter implements LifeLineElement.Position, LMMessageEnd.ConnectableLifeLineElement {
public BoundaryLifeLineElement(LifeLineElement.Position gdeElementPosition, int offset, int size) {
super(offset, size);
myGdeElementPosition = gdeElementPosition;
}
public int getPositionValue() {
return myGdeElementPosition.getPositionValue();
}
public void setPositionValue(int pos) {
setPositionValue(pos, false);
}
void setPositionValueFromMessage(int messagePos) {
int pos = messagePos - getMessagesVerticalPosOffset();
setPositionValue(pos, true);
}
public boolean isVirtual() {
return false;
}
public boolean isFirstPrioritedPosition() {
return myGdeElementPosition.isFirstPrioritedPosition();
}
public boolean isLastPrioritedPosition() {
return myGdeElementPosition.isLastPrioritedPosition();
}
public LifeLine getLifeLine() {
LMLifeLine lmLifeLine = LMGenCallOccurence.this.getLifeLine();
return lmLifeLine.getVerticalLayoutLifeLine();
}
public Position getPosition() {
return this;
}
List getLMMesssagesList() {
return myLMMessages;
}
public Enumeration afterConstraints() {
return myOrderingConstraintHolder.afterConstraints();
}
public Enumeration beforeConstraints() {
return myOrderingConstraintHolder.beforeConstraints();
}
public void addAfterConstraint(OrderingConstraint orderingConstraint) {
myOrderingConstraintHolder.addAfterConstraint(orderingConstraint);
}
public void addBeforeConstraint(OrderingConstraint orderingConstraint) {
myOrderingConstraintHolder.addBeforeConstraint(orderingConstraint);
}
public void removeAfterConstraint(OrderingConstraint orderingConstraint) {
myOrderingConstraintHolder
.removeAfterConstraint(orderingConstraint);
}
public void removeBeforeConstraint(OrderingConstraint orderingConstraint) {
myOrderingConstraintHolder
.removeBeforeConstraint(orderingConstraint);
}
abstract int getMessagesVerticalPosOffset();
protected void setPositionValue(int pos, boolean doNotReshapeMessages) {
//System.out.println("[LMLifeLineBracket.setPositionValue] to "+pos+", messages="+myLMMessages);
myGdeElementPosition.setPositionValue(pos);
if (!doNotReshapeMessages) {
int posForMessage = pos + getMessagesVerticalPosOffset();
for (int i=0; i<myLMMessages.size(); i++) {
LMMessage lmMessage = (LMMessage) myLMMessages.get(i);
setLMMessageEndVerticalPosition(lmMessage, posForMessage, i);
}
}
}
private final LifeLineElement.Position myGdeElementPosition;
private List myLMMessages = new ArrayList(1);
private final SDVerticalLayoutInputImpl.OrderingConstraintHolder myOrderingConstraintHolder = new SDVerticalLayoutInputImpl.OrderingConstraintHolder();
}
private final BoundaryLifeLineElement myTopLifeLineElement;
private final BoundaryLifeLineElement myBottomLifeLineElement;
private final LmBracketsList myChildBracketsList = new LmBracketsListSimple();
private LMCallMessageSynch myHorizontalConstraintCallMessage = null;
private LMLifeLine myLifelineToProvideBottomPos;
protected class PositioningGen implements LMMessageEnd.VerticalConstraintedPositioning {
public boolean canSetMessageAsHorizontalConstraint(LMCallMessageSynch lmCallMessageSynch) {
return myHorizontalConstraintCallMessage == null;
}
public void setMessageAsHorizontalConstraint(LMCallMessageSynch lmCallMessageSync, boolean isConstraint) {
if (isConstraint) {
if (myHorizontalConstraintCallMessage != null) {
throw new RuntimeException("Horizontal constraint is already set"); //$NON-NLS-1$
}
myHorizontalConstraintCallMessage = lmCallMessageSync;
if (false) {
//assert
myTopLifeLineElement.getHorizontalConstraint();
myBottomLifeLineElement.getHorizontalConstraint();
}
} else {
if (myHorizontalConstraintCallMessage != lmCallMessageSync) {
throw new RuntimeException("Cannot reset ANOTHER horizontal constraint"); //$NON-NLS-1$
}
myHorizontalConstraintCallMessage = null;
}
}
public boolean hasMessageAsHorizontalConstraint(LMCallMessageSynch lmCallMessageSynch) {
return myHorizontalConstraintCallMessage == lmCallMessageSynch;
}
public LMMessageEnd.ConnectableLifeLineElement getTopLifeLineElement() {
return getTopBoundaryLifeLineElement();
}
public LifeLineElement getBottomLifeLineElement() {
if (hasNoDuration()) {
//bottom position is constrained by top position
//and cannot participate in horizontal constraints
return null;
}
return getBottomBoundaryLifeLineElement();
}
public LMLifeLine getLifeLine() {
return LMGenCallOccurence.this.getLifeLine();
}
}
protected boolean calculateIsBracketConsistent() {
return super.calculateIsBracketConsistent() && isIncomingOutgoingMessagesOK();
}
protected boolean isIncomingOutgoingMessagesOK() {
List topMessages = getTopBoundaryLifeLineElement().getLMMesssagesList();
List bottomMessages = getBottomBoundaryLifeLineElement().getLMMesssagesList();
int sumSize = topMessages.size()+bottomMessages.size();
if (sumSize==0) {
return false;
}
if (sumSize>2) {
return false;
}
return true;
}
}