package org.eclipse.uml2.diagram.sequence.edit.create;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.uml2.diagram.common.editpolicies.U2TCreateParameters;
import org.eclipse.uml2.diagram.common.editpolicies.U2TCreateParametersImpl;
import org.eclipse.uml2.diagram.sequence.anchor.SDModelUtil;
import org.eclipse.uml2.diagram.sequence.edit.parts.ActionExecutionSpecificationEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.BehaviorExecutionSpecificationEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.CombinedFragmentMountingRegionEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.InteractionEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.InteractionOperandMountingRegionEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.InteractionUseMountingRegionEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.LayeredCombinedFragmentEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.LayeredOperandEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.LifelineEditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.StateInvariantEditPart;
import org.eclipse.uml2.diagram.sequence.edit.policies.InteractionNestedLayoutRequest;
import org.eclipse.uml2.diagram.sequence.edit.policies.OrderedLayoutEditPolicy;
import org.eclipse.uml2.diagram.sequence.model.SDModelAccess;
import org.eclipse.uml2.diagram.sequence.model.edit.CreateCombinedFragment;
import org.eclipse.uml2.diagram.sequence.model.edit.SDAnchor;
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.SDLifeLine;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDModel;
import org.eclipse.uml2.diagram.sequence.model.sequenced.SDMountingRegion;
import org.eclipse.uml2.diagram.sequence.part.UMLVisualIDRegistry;
import org.eclipse.uml2.uml.BehaviorExecutionSpecification;
import org.eclipse.uml2.uml.CombinedFragment;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.InteractionOperand;
import org.eclipse.uml2.uml.Lifeline;
public class CreateCombinedFragmentEditPolicy extends AbstractCreateSDElementEditPolicy {
@Override
public void activate() {
super.activate();
}
@Override
public boolean understandsRequest(Request req) {
if (req instanceof CreateInteractionUseRequest){
return true;
}
if (req instanceof CreateCombinedFragmentRequest){
return true;
}
return super.understandsRequest(req);
}
@Override
public Command getCommand(Request request) {
if (request instanceof CreateCombinedFragmentRequest){
return createCombinedFragment((CreateCombinedFragmentRequest)request);
}
return super.getCommand(request);
}
private SDBracketContainer findHostBracketContainer(SDModel sdModel){
Element umlHost = (Element) getHostImpl().getNotationView().getElement();
if (umlHost instanceof BehaviorExecutionSpecification){
return sdModel.getUMLTracing().findBehaviorSpec((BehaviorExecutionSpecification)umlHost);
}
if (umlHost instanceof Lifeline){
return sdModel.getUMLTracing().findLifeLine((Lifeline)umlHost);
}
if (umlHost instanceof InteractionOperand){
SDFrame sdFrame = sdModel.getUMLTracing().findInteractionOperand((InteractionOperand)umlHost);
Lifeline onLifeline = (Lifeline) findLifeLineEditPart(getHostImpl()).resolveSemanticElement();
return sdFrame.findRegionForUmlLifeLine(onLifeline);
}
throw new IllegalStateException("EditPolicy " + this + " is not expected to be registered for host : " + umlHost);
}
private Command createCombinedFragment(final CreateCombinedFragmentRequest request){
LifelineEditPart lifeLineEP = findLifeLineEditPart(getHostImpl());
final Lifeline umlLifeline = (Lifeline) lifeLineEP.resolveSemanticElement();
final SDModel sdModel = SDModelAccess.findSDModel(getHostImpl().getNotationView());
final SDBracketContainer sdHost = findHostBracketContainer(sdModel);
final IGraphicalEditPart frameContainerEP = findFrameContainerEditPart(sdHost);
final U2TCreateParameters createParams = U2TCreateParametersImpl.createFor(getHostImpl(), request);
final OrderedLayoutEditPolicy.AnchoredSibling diagramAnchor = computeAnchoredSibling(createParams);
final SDAnchor sdAnchor;
if (diagramAnchor == null || diagramAnchor.isBeforeNotAfterAnchor()){
sdAnchor = SDAnchor.firstChildFor(sdHost);
} else {
sdAnchor = createSDAfterAnchor(diagramAnchor, sdModel, umlLifeline);
}
final Helper2 helper2 = new Helper2(request.getPreferencesHint());
final ShowDialogCommand dialog_ = request.isTieRequest() ? null : new ShowDialogCommand(getEditingDomain());
AbstractTransactionalCommand doTheJob = new AbstractTransactionalCommand(getEditingDomain(), "", Collections.emptyList()){
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
SDCombinedFragment result;
if (request.isTieRequest()){
CreateCombinedFragment creator = new CreateCombinedFragment(sdModel);
creator.tieCombinedFragment(request.getFragmentToTie(), sdHost, sdAnchor);
result = request.getFragmentToTie();
} else {
ChooseOperatorDialog.OperatorProperties config = dialog_.getOperatorProperties();
if (config == null){
return CommandResult.newCancelledCommandResult();
}
CreateCombinedFragment creator = new CreateCombinedFragment(sdModel);
result = creator.createCombinedFragment(sdHost, sdAnchor, config.getOperatorKind(), config.getNumberOfOperands());
}
if (result == null){
return CommandResult.newErrorCommandResult("Failed to created combined fragment in SDModel");
}
CombinedFragment umlResult = result.getUmlCombinedFragment();
SDMountingRegion combinedMounter = result.findRegionForUmlLifeLine(umlLifeline);
Node combinedMounterView = helper2.createNode(//
getHostImpl().getNotationView(), umlResult, CombinedFragmentMountingRegionEditPart.VISUAL_ID, diagramAnchor);
if (combinedMounterView == null){
throw new IllegalStateException("Can't create combined mounter view for sd-mounter: " + combinedMounter);
}
if (createParams.getRelativeLocation() != null){
Point relativeLocation = createParams.getRelativeLocation();
//ViewUtil.setStructuralFeatureValue(combinedMounterView, NotationPackage.eINSTANCE.getLocation_X(), Integer.valueOf(relativeLocation.x));
ViewUtil.setStructuralFeatureValue(combinedMounterView, NotationPackage.eINSTANCE.getLocation_Y(), Integer.valueOf(relativeLocation.y));
}
if (request.getSize() != null){
ViewUtil.setStructuralFeatureValue(combinedMounterView, NotationPackage.eINSTANCE.getSize_Height(), Integer.valueOf(request.getSize().height));
ViewUtil.setStructuralFeatureValue(combinedMounterView, NotationPackage.eINSTANCE.getSize_Width(), Integer.valueOf(request.getSize().width));
}
//XXX: consider frames anchor!
View framesAnchor;
Node combinedFrameView_;
if (request.isTieRequest()){
combinedFrameView_ = request.getFragmentToTieView();
} else {
combinedFrameView_ = helper2.createNode(//
frameContainerEP.getNotationView(), umlResult, LayeredCombinedFragmentEditPart.VISUAL_ID, null);
}
Edge combinedMountingLink = helper2.createMountingLink(combinedMounterView, combinedFrameView_);
for (SDBracket nextOperandMounter : combinedMounter.getBrackets()){
if (nextOperandMounter instanceof SDMountingRegion){
Node nextOperandMounterView = helper2.createNode(//
combinedMounterView, nextOperandMounter.getUmlFragment(), InteractionOperandMountingRegionEditPart.VISUAL_ID, null);
if (nextOperandMounterView == null){
throw new IllegalStateException("Can't create operand mounter view for sd-mounter: " + nextOperandMounter);
}
Node nextOperandFrameView;
if (request.isTieRequest()){
nextOperandFrameView = findChildNodeByVisualIdAndSemanticElement(combinedFrameView_, LayeredOperandEditPart.VISUAL_ID, nextOperandMounter.getUmlFragment());
} else {
nextOperandFrameView = helper2.createNode(//
combinedFrameView_, nextOperandMounter.getUmlFragment(), LayeredOperandEditPart.VISUAL_ID, null);
}
if (nextOperandFrameView == null){
throw new IllegalStateException("Can't create operand frame view for sd-mounter: " + nextOperandMounter);
}
Edge operandMountingLink = helper2.createMountingLink(nextOperandMounterView, nextOperandFrameView);
}
}
return CommandResult.newOKCommandResult();
}
private Node findChildNodeByVisualIdAndSemanticElement(Node node, int visualId, EObject semantic){
for (Object next : node.getChildren()){
if (next instanceof Node){
Node nextNode = (Node)next;
if (UMLVisualIDRegistry.getVisualID(nextNode) == visualId && semantic == nextNode.getElement()){
return nextNode;
}
}
}
return null;
}
};
InteractionNestedLayoutRequest layoutRequest = new InteractionNestedLayoutRequest();
layoutRequest.requestTotalLayout();
Command layoutCommand = getLayoutCommand(layoutRequest);
GEFAwareCompositeCommand result = new GEFAwareCompositeCommand(getHostImpl().getEditingDomain(), "Creating Combined Fragment");
if (dialog_ != null){
result.add(dialog_);
}
result.add(doTheJob);
Command main = new ICommandProxy(result);
return postScheduleLayout(main, layoutCommand);
}
private GraphicalEditPart findFrameContainerEditPart(SDBracketContainer sdHost){
InteractionEditPart interactionEP = (InteractionEditPart) findLifeLineEditPart(getHostImpl()).getParent();
if (sdHost instanceof SDLifeLine){
return interactionEP;
}
if (sdHost instanceof SDMountingRegion){
SDMountingRegion mounter = (SDMountingRegion)sdHost;
SDFrame sdFrame = mounter.getFrame();
return findFrameEditPart(interactionEP, sdFrame);
}
throw new IllegalStateException("Unknown SDBracketContainer: " + sdHost);
}
private static GraphicalEditPart findFrameEditPart(InteractionEditPart interactionEP, SDFrame sdFrame){
if (sdFrame == null){
return interactionEP;
}
GraphicalEditPart nextEP = interactionEP;
List<SDFrame> frames;
try {
frames = SDModelUtil.collectEnclosingFrames(sdFrame, new ArrayList<SDFrame>());
Collections.reverse(frames);
} catch (SDModelUtil.AlienElementException e){
throw new IllegalStateException(e);
}
for (SDFrame nextFrame : frames){
nextEP = (GraphicalEditPart) nextEP.findEditPart(null, nextFrame.getUmlFragment());
if (nextEP == null){
throw new IllegalStateException(//
"Can't find frame editpart for SDFrame: " + nextFrame + //
", while searching for deep frame: " + sdFrame);
}
}
return nextEP;
}
private static class ShowDialogCommand extends AbstractTransactionalCommand {
private ChooseOperatorDialog.OperatorProperties myProperties;
public ShowDialogCommand(TransactionalEditingDomain domain){
super(domain, "Select", Collections.emptyList());
}
public ChooseOperatorDialog.OperatorProperties getOperatorProperties() {
return myProperties;
}
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
ChooseOperatorDialog dialog = new ChooseOperatorDialog(Display.getCurrent().getActiveShell());
if (Window.OK == dialog.open()) {
myProperties = dialog.getResult();
return CommandResult.newOKCommandResult();
}
return CommandResult.newCancelledCommandResult();
}
}
private OrderedLayoutEditPolicy.AnchoredSibling computeAnchoredSibling(U2TCreateParameters createParams){
Point relativeLocation = createParams.getRelativeLocation();
if (relativeLocation != null && getHost().getEditPolicy(EditPolicy.LAYOUT_ROLE) instanceof OrderedLayoutEditPolicy){
OrderedLayoutEditPolicy layout = (OrderedLayoutEditPolicy)getHost().getEditPolicy(EditPolicy.LAYOUT_ROLE);
return layout.findAnchoredSibling(relativeLocation);
}
return null;
}
private SDAnchor createSDAfterAnchor(OrderedLayoutEditPolicy.AnchoredSibling anchor, SDModel sdModel, Lifeline onUmlLifeline){
if (anchor.isBeforeNotAfterAnchor()){
throw new IllegalArgumentException("I am for 'after' anchors only");
}
View notationAnchor = anchor.getSiblingView();
SDBracket sdAnchor;
switch(UMLVisualIDRegistry.getVisualID(notationAnchor)){
case BehaviorExecutionSpecificationEditPart.VISUAL_ID :
{
BehaviorExecutionSpecification umlSpec = (BehaviorExecutionSpecification)notationAnchor.getElement();
sdAnchor = sdModel.getUMLTracing().findBehaviorSpec(umlSpec);
break;
}
case CombinedFragmentMountingRegionEditPart.VISUAL_ID:
{
CombinedFragment umlFrame = (CombinedFragment)notationAnchor.getElement();
SDFrame sdFrame = sdModel.getUMLTracing().findCombinedFragment(umlFrame);
sdAnchor = sdFrame.findRegionForUmlLifeLine(onUmlLifeline);
break;
}
case StateInvariantEditPart.VISUAL_ID:
case ActionExecutionSpecificationEditPart.VISUAL_ID:
case InteractionUseMountingRegionEditPart.VISUAL_ID:
{
throw new UnsupportedOperationException("Not yet implemented");
}
default: {
throw new IllegalStateException("Unknown/unexpected anchor view found: " + notationAnchor);
}
}
return SDAnchor.after(sdAnchor);
}
}