package org.eclipse.uml2.diagram.sequence.model.edit;
import java.util.ListIterator;
import org.eclipse.uml2.diagram.sequence.model.builder.SDBuilderTrace;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDBracket;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDBracketContainer;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDCombinedFragment;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDFrame;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDFrameContainer;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDInteractionOperand;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDLifeLine;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDModel;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDMountingRegion;
import org.eclipse.uml2.uml.CombinedFragment;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.InteractionOperand;
import org.eclipse.uml2.uml.InteractionOperatorKind;
import org.eclipse.uml2.uml.UMLFactory;
public class CreateCombinedFragment {
private final SDModel myModel;
public CreateCombinedFragment(SDModel model){
myModel = model;
}
public SDCombinedFragment tieCombinedFragment(SDCombinedFragment sdCombined, SDBracketContainer container, SDAnchor anchor){
SDLifeLine sdLifeLine = container.getCoveredLifeLine();
if (sdLifeLine.getModel() != myModel){
throw new IllegalArgumentException(//
"Alien lifeline: " + sdLifeLine + //
", for sdModel: " + myModel);
}
if (anchor != null && !anchor.isFirstElement() && anchor.getAnchor().getBracketContainer() != container){
throw new IllegalArgumentException(//
"Anchor: " + anchor.getAnchor() + //
", is not applicable to container: " + container + //
", actual container is: " + anchor.getAnchor().getBracketContainer());
}
CreateContainer createContainer = findCreateContainer(container, anchor);
CombinedFragment umlCombined = sdCombined.getUmlCombinedFragment();
umlCombined.getCovereds().add(sdLifeLine.getUmlLifeline());
sdCombined.getCoveredLifeLines().add(sdLifeLine);
SDMountingRegion sdCombinedMounter = getTraceImpl().bindNewMountingRegion(sdCombined);
for (int i = 0; i < umlCombined.getOperands().size(); i++){
InteractionOperand nextUMLOperand = umlCombined.getOperands().get(i);
nextUMLOperand.getCovereds().add(sdLifeLine.getUmlLifeline());
SDInteractionOperand nextSDOperand = getTraceImpl().findInteractionOperand(nextUMLOperand);
nextSDOperand.getCoveredLifeLines().add(sdLifeLine);
SDMountingRegion nextOperandMounter = getTraceImpl().bindNewMountingRegion(nextSDOperand);
sdCombinedMounter.getBrackets().add(nextOperandMounter);
}
createContainer.getSDBracketInsertPosition().add(sdCombinedMounter);
return sdCombined;
}
public SDCombinedFragment createCombinedFragment(SDBracketContainer container, SDAnchor anchor, InteractionOperatorKind kind, int operandsCount){
SDLifeLine sdLifeLine = container.getCoveredLifeLine();
if (sdLifeLine.getModel() != myModel){
throw new IllegalArgumentException(//
"Alien lifeline: " + sdLifeLine + //
", for sdModel: " + myModel);
}
if (anchor != null && !anchor.isFirstElement() && anchor.getAnchor().getBracketContainer() != container){
throw new IllegalArgumentException(//
"Anchor: " + anchor.getAnchor() + //
", is not applicable to container: " + container + //
", actual container is: " + anchor.getAnchor().getBracketContainer());
}
CreateContainer createContainer = findCreateContainer(container, anchor);
if (createContainer == null){
return null;
}
CombinedFragment umlCombined = UMLFactory.eINSTANCE.createCombinedFragment();
umlCombined.getCovereds().add(sdLifeLine.getUmlLifeline());
umlCombined.setInteractionOperator(kind);
SDCombinedFragment sdCombined = getTraceImpl().bindNewCombinedFragment(umlCombined);
sdCombined.getCoveredLifeLines().add(sdLifeLine);
SDMountingRegion sdCombinedMounter = getTraceImpl().bindNewMountingRegion(sdCombined);
for (int i = 0; i < operandsCount; i++){
InteractionOperand nextUMLOperand = umlCombined.createOperand(null);
nextUMLOperand.getCovereds().add(sdLifeLine.getUmlLifeline());
SDInteractionOperand nextSDOperand = getTraceImpl().bindNewInteractionOperand(nextUMLOperand);
sdCombined.getFrames().add(nextSDOperand);
nextSDOperand.getCoveredLifeLines().add(sdLifeLine);
SDMountingRegion nextOperandMounter = getTraceImpl().bindNewMountingRegion(nextSDOperand);
sdCombinedMounter.getBrackets().add(nextOperandMounter);
}
createContainer.getUMLInsertPosition().add(umlCombined);
createContainer.getSDBracketInsertPosition().add(sdCombinedMounter);
createContainer.getSDFrameInsertPosition().add(sdCombined);
return sdCombined;
}
private CreateContainer findCreateContainer(SDBracketContainer sdContainer, SDAnchor anchor){
if (sdContainer instanceof SDLifeLine){
return new OnLifelineCreateContainer((SDLifeLine)sdContainer, anchor);
}
if (sdContainer instanceof SDMountingRegion){
SDMountingRegion mountingRegion = (SDMountingRegion)sdContainer;
if (mountingRegion.getFrame() instanceof SDInteractionOperand){
return new OnInteractionOperandMounterCreateContainer(mountingRegion, anchor);
}
}
return null;
}
private static interface CreateContainer {
public ListIterator<InteractionFragment> getUMLInsertPosition();
public ListIterator<SDFrame> getSDFrameInsertPosition();
public ListIterator<SDBracket> getSDBracketInsertPosition();
}
private static abstract class AbstractCreateContainer implements CreateContainer {
private final SDBracketContainer myBracketContainer;
private final SDAnchor myAnchor;
public AbstractCreateContainer(SDBracketContainer bracketContainer, SDAnchor anchor){
assert anchor.isFirstElement() || bracketContainer == anchor.getAnchor().getBracketContainer();
myBracketContainer = bracketContainer;
myAnchor = anchor;
}
protected boolean isAfterAnchor(){
return myAnchor != null && !myAnchor.isFirstElement() && !myAnchor.isBeforeNotAfterAnchor();
}
public ListIterator<SDFrame> getSDFrameInsertPosition() {
SDFrameContainer frameContainer = getFrameContainer();
InsertAfter<SDFrame> theFramesPast = new InsertAfter<SDFrame>();
if (isAfterAnchor()){
for (SDBracket nextBracketBefore : myBracketContainer.getBrackets()){
if (nextBracketBefore == myAnchor.getAnchor()){
break;
}
if (nextBracketBefore instanceof SDMountingRegion){
theFramesPast.considerAsPast(((SDMountingRegion)nextBracketBefore).getFrame());
}
}
}
return theFramesPast.getAfterThePastPosition(frameContainer.getFrames());
}
public ListIterator<SDBracket> getSDBracketInsertPosition() {
InsertAfter<SDBracket> theBracketsPast = new InsertAfter<SDBracket>();
if (isAfterAnchor()){
theBracketsPast.considerAsPast(myAnchor.getAnchor());
}
return theBracketsPast.getAfterThePastPosition(myBracketContainer.getBrackets());
}
public ListIterator<InteractionFragment> getUMLInsertPosition() {
InsertFragmentAfter umlPast = new InsertFragmentAfter();
if (isAfterAnchor()){
umlPast.bracketFinished(myAnchor.getAnchor());
}
return umlPast.getAfterThePastPosition(getFrameContainer().getFragmentsList());
}
protected final SDBracketContainer getBracketContainer() {
return myBracketContainer;
}
protected final SDAnchor getAnchor() {
return myAnchor;
}
protected abstract SDFrameContainer getFrameContainer();
}
private static class OnLifelineCreateContainer extends AbstractCreateContainer {
public OnLifelineCreateContainer(SDLifeLine lifeLine, SDAnchor anchor){
super(lifeLine, anchor);
}
@Override
protected SDFrameContainer getFrameContainer() {
return getLifeline().getModel();
}
protected final SDLifeLine getLifeline(){
return (SDLifeLine)getBracketContainer();
}
}
private static class OnInteractionOperandMounterCreateContainer extends AbstractCreateContainer {
public OnInteractionOperandMounterCreateContainer(SDMountingRegion region, SDAnchor anchor){
super(region, anchor);
if (false == region.getFrame() instanceof SDInteractionOperand){
throw new IllegalArgumentException("Only SDInteractionOperand is valid frame with some allowed contents of its mounting regions, " + region);
}
}
@Override
protected SDFrameContainer getFrameContainer() {
return getSDInteractionOperand();
}
protected final SDMountingRegion getMountingRegion(){
return (SDMountingRegion)getBracketContainer();
}
protected final SDInteractionOperand getSDInteractionOperand(){
return (SDInteractionOperand)getMountingRegion().getFrame();
}
}
private SDBuilderTrace getTraceImpl(){
//intentional implementation cast
return (SDBuilderTrace)myModel.getUMLTracing();
}
}