/*****************************************************************************
* Copyright (c) 2010 CEA
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Saadia DHOUIB (CEA LIST) saadia.dhouib@cea.fr
* Vincent LORENZO (CEA-LIST) vincent.lorenzo@cea.fr
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.communication.custom.edit.policies;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor;
import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.IHintedType;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.common.commands.SemanticAdapter;
import org.eclipse.papyrus.uml.diagram.common.editpolicies.OldCommonDiagramDragDropEditPolicy;
import org.eclipse.papyrus.uml.diagram.common.util.ViewServiceUtil;
import org.eclipse.papyrus.uml.diagram.communication.custom.commands.CommunicationDeferredCreateConnectionViewCommand;
import org.eclipse.papyrus.uml.diagram.communication.custom.commands.CustomMessageViewCreateCommand;
import org.eclipse.papyrus.uml.diagram.communication.custom.helper.CommunicationLinkMappingHelper;
import org.eclipse.papyrus.uml.diagram.communication.custom.helper.CommunicationUtil;
import org.eclipse.papyrus.uml.diagram.communication.custom.helper.DiagramShortCutHelper;
import org.eclipse.papyrus.uml.diagram.communication.custom.helper.DurationObservationHelper;
import org.eclipse.papyrus.uml.diagram.communication.custom.helper.TimeObservationHelper;
import org.eclipse.papyrus.uml.diagram.communication.edit.parts.CommentEditPartCN;
import org.eclipse.papyrus.uml.diagram.communication.edit.parts.ConstraintEditPartCN;
import org.eclipse.papyrus.uml.diagram.communication.edit.parts.DurationObservationEditPartCN;
import org.eclipse.papyrus.uml.diagram.communication.edit.parts.LifelineEditPartCN;
import org.eclipse.papyrus.uml.diagram.communication.edit.parts.MessageEditPart;
import org.eclipse.papyrus.uml.diagram.communication.edit.parts.ShortCutDiagramEditPart;
import org.eclipse.papyrus.uml.diagram.communication.edit.parts.TimeObservationEditPartCN;
import org.eclipse.papyrus.uml.diagram.communication.part.UMLVisualIDRegistry;
import org.eclipse.papyrus.uml.diagram.communication.providers.UMLElementTypes;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.DurationObservation;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Interaction;
import org.eclipse.uml2.uml.Lifeline;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.TimeObservation;
/**
* A policy to support dNd from the Model Explorer in the communication diagram.
*/
public class CustomDiagramDragDropEditPolicy extends OldCommonDiagramDragDropEditPolicy {
/**
* Instantiates a new custom diagram drag drop edit policy.
*/
public CustomDiagramDragDropEditPolicy() {
super(CommunicationLinkMappingHelper.getInstance());
}
/**
* Gets the UML element type.
*
* @param elementID
* the element id
* @return the UML element type {@inheritDoc}
*/
@Override
public IElementType getUMLElementType(int elementID) {
return UMLElementTypes.getElementType(elementID);
}
/**
* Gets the node visual id.
*
* @param containerView
* the container view
* @param domainElement
* the domain element
* @return the node visual id {@inheritDoc}
*/
@Override
public int getNodeVisualID(View containerView, EObject domainElement) {
return UMLVisualIDRegistry.getNodeVisualID(containerView, domainElement);
}
/**
* Gets the link with class visual id.
*
* @param domainElement
* the domain element
* @return the link with class visual id {@inheritDoc}
*/
@Override
public int getLinkWithClassVisualID(EObject domainElement) {
return UMLVisualIDRegistry.getLinkWithClassVisualID(domainElement);
}
/**
* @see org.eclipse.papyrus.uml.diagram.common.editpolicies.CommonDiagramDragDropEditPolicy#getSpecificDropCommand(org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest,
* org.eclipse.uml2.uml.Element, int, int)
*
* @param dropRequest
* @param semanticElement
* @param nodeVISUALID
* @param linkVISUALID
* @return
*/
@Override
protected Command getSpecificDropCommand(DropObjectsRequest dropRequest, Element semanticElement, int nodeVISUALID, int linkVISUALID) {
switch(linkVISUALID) {
case MessageEditPart.VISUAL_ID:
return dropMessage(dropRequest, semanticElement, linkVISUALID);
default:
// Switch test over nodeVISUALID
switch(nodeVISUALID) {
case LifelineEditPartCN.VISUAL_ID:
return dropChildNode(dropRequest, semanticElement, nodeVISUALID);
// case CommentEditPartCN.VISUAL_ID:
// return dropChildNode(dropRequest, semanticElement, nodeVISUALID);
// case ConstraintEditPartCN.VISUAL_ID:
// return dropChildNode(dropRequest, semanticElement, nodeVISUALID);
case TimeObservationEditPartCN.VISUAL_ID:
return dropTimeObservation(dropRequest, (TimeObservation)semanticElement, nodeVISUALID);
case DurationObservationEditPartCN.VISUAL_ID:
return dropDurationObservation(dropRequest, (DurationObservation)semanticElement, nodeVISUALID);
case CommentEditPartCN.VISUAL_ID:
return dropComment(dropRequest, semanticElement, nodeVISUALID);
case ConstraintEditPartCN.VISUAL_ID:
return dropConstraint(dropRequest, semanticElement, nodeVISUALID);
default:
return super.getSpecificDropCommand(dropRequest, semanticElement, nodeVISUALID, linkVISUALID);
}
}
}
/**
* Returns the command to drop the Comment + the link to attach it to its annotated elements
*
* @param dropRequest
* the drop request
* @param semanticLink
* the semantic link
* @param nodeVISUALID
* the node visual id
*
* @return the command
*/
protected Command dropComment(DropObjectsRequest dropRequest, Element semanticLink, int nodeVISUALID) {
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
if(!(graphicalParentObject instanceof Interaction)) {
return UnexecutableCommand.INSTANCE;
}
return getDropCommentCommand((Comment)semanticLink, getViewer(), getDiagramPreferencesHint(), dropRequest.getLocation(), ((GraphicalEditPart)getHost()).getNotationView(), (IHintedType)UMLElementTypes.Comment_8005, (IHintedType)UMLElementTypes.CommentAnnotatedElement_8010);
}
/**
* Returns the command to drop the Constraint + the link to attach it to its contrainted elements
*
* @param dropRequest
* the drop request
* @param semanticLink
* the semantic link
* @param nodeVISUALID
* the node visual id
*
* @return the command
*/
protected Command dropConstraint(DropObjectsRequest dropRequest, Element semanticLink, int nodeVISUALID) {
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
if(!(graphicalParentObject instanceof Interaction)) {
return UnexecutableCommand.INSTANCE;
}
return getDropConstraintCommand((Constraint)semanticLink, getViewer(), getDiagramPreferencesHint(), dropRequest.getLocation(), ((GraphicalEditPart)getHost()).getNotationView(), (IHintedType)UMLElementTypes.Constraint_8004, (IHintedType)UMLElementTypes.ConstraintConstrainedElement_8011);
}
/**
* Returns the drop command for TimeObservation nodes.
*
* @param dropRequest
* the drop request
* @param droppedElement
* the element to drop
* @param nodeVISUALID
* the visual identifier of the EditPart of the dropped element
* @return the drop command
*/
protected Command dropTimeObservation(DropObjectsRequest dropRequest, TimeObservation droppedElement, int nodeVISUALID) {
// Test canvas element
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
if(!(graphicalParentObject instanceof org.eclipse.uml2.uml.Interaction)) {
return UnexecutableCommand.INSTANCE;
}
TimeObservationHelper timeObservationHelper = new TimeObservationHelper(getEditingDomain());
return timeObservationHelper.dropTimeObservation(droppedElement, getViewer(), getDiagramPreferencesHint(), dropRequest.getLocation(), ((GraphicalEditPart)getHost()).getNotationView());
}
/**
* Returns the drop command for ShortCutDiagram nodes.
*
* @param dropRequest
* the drop request
* @param droppedElement
* the element to drop
* @param nodeVISUALID
* the visual identifier of the EditPart of the dropped element
* @return the drop command
*/
protected Command dropShortCutDiagram(DropObjectsRequest dropRequest, Diagram droppedElement, int nodeVISUALID) {
// Test canvas element
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
if(!(graphicalParentObject instanceof org.eclipse.uml2.uml.Interaction)) {
return UnexecutableCommand.INSTANCE;
}
DiagramShortCutHelper diagramShortCutHelper = new DiagramShortCutHelper(getEditingDomain());
return diagramShortCutHelper.dropDiagramShortCut(droppedElement, getViewer(), getDiagramPreferencesHint(), dropRequest.getLocation(), ((GraphicalEditPart)getHost()).getNotationView());
}
/**
* <pre>
* This method return a drop command for a childnode (comment or constraint).
* It returns an {@link org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand} in
* case the element is dropped on a canvas referencing a domain element that is not a Package.
* </pre>
*
* @param dropRequest
* the drop request
* @param semanticElement
* the semantic element
* @param nodeVISUALID
* the visual identifier of the EditPart of the dropped element
*
* @return the drop command
*/
protected Command dropChildNode(DropObjectsRequest dropRequest, Element semanticElement, int nodeVISUALID) {
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
if(graphicalParentObject instanceof org.eclipse.uml2.uml.Interaction) {
return new ICommandProxy(getDefaultDropNodeCommand(nodeVISUALID, dropRequest.getLocation(), semanticElement));
}
return UnexecutableCommand.INSTANCE;
}
/**
* Returns the drop command for DurationObservation nodes.
*
* @param dropRequest
* the drop request
* @param droppedElement
* the element to drop
* @param nodeVISUALID
* the visual identifier of the EditPart of the dropped element
* @return the drop command
*/
protected Command dropDurationObservation(DropObjectsRequest dropRequest, DurationObservation droppedElement, int nodeVISUALID) {
// Test canvas element
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
if(!(graphicalParentObject instanceof org.eclipse.uml2.uml.Interaction)) {
return UnexecutableCommand.INSTANCE;
}
DurationObservationHelper durationObservationHelper = new DurationObservationHelper(getEditingDomain());
return durationObservationHelper.dropDurationObservation(droppedElement, getViewer(), getDiagramPreferencesHint(), dropRequest.getLocation(), ((GraphicalEditPart)getHost()).getNotationView());
}
/**
* Returns the drop command for Message links.
*
* @param dropRequest
* the drop request
*
* @param semanticLink
* the link to drop
* @param linkVISUALID
* the visual identifier of the EditPart of the dropped element
* @return the drop command
*
*/
public Command dropMessage(DropObjectsRequest dropRequest, Element semanticLink, int linkVISUALID) {
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
if(!(graphicalParentObject instanceof org.eclipse.uml2.uml.Interaction)) {
return UnexecutableCommand.INSTANCE;
}
if(semanticLink instanceof Message) {//if the drop request concerns a UML message
//1. verify if source and target of the message are already connected
Collection<?> sources = CommunicationLinkMappingHelper.getInstance().getSource(semanticLink);
Collection<?> targets = CommunicationLinkMappingHelper.getInstance().getTarget(semanticLink);
if(!sources.isEmpty() && !targets.isEmpty()) {
Element source = (Element)sources.toArray()[0];
Element target = (Element)targets.toArray()[0];
if((source instanceof Lifeline) && (target instanceof Lifeline)) {
Set<Message> messages = CommunicationUtil.verifyUMLLifelinesConnected((Lifeline)source, (Lifeline)target);
if(!(messages == null) && (messages.size() >= 1)) {//the UML lifelines are already connected by one or more than one more message
//1. search for the edit parts of the messages
List<EditPart> messagesEP = null;
for(Message current : messages) {
EditPart messageEP = lookForEditPart(current);
if(!(messageEP == null)) {
if(messagesEP == null) {
messagesEP = new ArrayList<EditPart>();
messagesEP.add(messageEP);
} else {
messagesEP.add(messageEP);
}
}
}
//System.err.println("Messages edit parts on the link :" + messagesEP);
//System.err.println("Semantic messages on the link :" + messages);
//2. Create the drop commands
if(messagesEP == null) {//There is no graphical connection between the two lifelines (in this diagram)
//create a dropMessageAsConnector Command
return new ICommandProxy(dropMessageAsConnector(new CompositeCommand("drop Message"), source, target, linkVISUALID, dropRequest.getLocation(), semanticLink)); //$NON-NLS-1$
} else {//add the message as a label of the graphical connector
ConnectionEditPart conEP = (ConnectionEditPart)messagesEP.get(0).getParent();
IAdaptable linkAdapter = new SemanticAdapter(semanticLink, null);
//location where the label will be dropped
Point loc = new Point(1, -23);
//reuse of the CustomMessageViewCreateCommand
return new ICommandProxy(new CustomMessageViewCreateCommand(((IGraphicalEditPart)getHost()).getEditingDomain(), conEP.getViewer(), ((IGraphicalEditPart)conEP).getDiagramPreferencesHint(), loc, linkAdapter, conEP));
}
}
}
}
}
return UnexecutableCommand.INSTANCE;
}
/**
* the method provides command to drop the messages into the diagram.
* If the source and the target views do not exist, these views will be created.
*
* @param cc
* the composite command that will contain the set of command to create the message
* @param source
* the source the element source of the link
* @param target
* the target the element target of the link
* @param linkVISUALID
* the link VISUALID used to create the view
* @param location
* the location the location where the view will be be created
* @param semanticLink
* the semantic link that will be attached to the view
*
* @return the composite command
*/
public CompositeCommand dropMessageAsConnector(CompositeCommand cc, Element source, Element target, int linkVISUALID, Point location, Element semanticLink) {
// look for editpart
GraphicalEditPart sourceEditPart = (GraphicalEditPart)lookForEditPart(source);
GraphicalEditPart targetEditPart = (GraphicalEditPart)lookForEditPart(target);
// descriptor of the link
CreateConnectionViewRequest.ConnectionViewDescriptor linkdescriptor = new CreateConnectionViewRequest.ConnectionViewDescriptor(getUMLElementType(linkVISUALID), ((IHintedType)getUMLElementType(linkVISUALID)).getSemanticHint(), getDiagramPreferencesHint());
IAdaptable sourceAdapter = null;
IAdaptable targetAdapter = null;
if(sourceEditPart == null) {
// creation of the node
ViewDescriptor descriptor = new ViewDescriptor(new EObjectAdapter(source), Node.class, null, ViewUtil.APPEND, false, ((IGraphicalEditPart)getHost()).getDiagramPreferencesHint());
// get the command and execute it.
CreateCommand nodeCreationCommand = new CreateCommand(((IGraphicalEditPart)getHost()).getEditingDomain(), descriptor, ((View)getHost().getModel()));
cc.compose(nodeCreationCommand);
SetBoundsCommand setBoundsCommand = new SetBoundsCommand(getEditingDomain(), "move", (IAdaptable)nodeCreationCommand.getCommandResult().getReturnValue(), new Point(location.x, location.y + 100)); //$NON-NLS-1$
cc.compose(setBoundsCommand);
sourceAdapter = (IAdaptable)nodeCreationCommand.getCommandResult().getReturnValue();
} else {
sourceAdapter = new SemanticAdapter(null, sourceEditPart.getModel());
}
if(targetEditPart == null) {
// creation of the node
ViewDescriptor descriptor = new ViewDescriptor(new EObjectAdapter(target), Node.class, null, ViewUtil.APPEND, false, ((IGraphicalEditPart)getHost()).getDiagramPreferencesHint());
// get the command and execute it.
CreateCommand nodeCreationCommand = new CreateCommand(((IGraphicalEditPart)getHost()).getEditingDomain(), descriptor, ((View)getHost().getModel()));
cc.compose(nodeCreationCommand);
SetBoundsCommand setBoundsCommand = new SetBoundsCommand(getEditingDomain(), "move", (IAdaptable)nodeCreationCommand.getCommandResult().getReturnValue(), new Point(location.x, location.y - 100)); //$NON-NLS-1$
cc.compose(setBoundsCommand);
targetAdapter = (IAdaptable)nodeCreationCommand.getCommandResult().getReturnValue();
} else {
targetAdapter = new SemanticAdapter(null, targetEditPart.getModel());
}
CommunicationDeferredCreateConnectionViewCommand aLinkCommand = new CommunicationDeferredCreateConnectionViewCommand(((IGraphicalEditPart)getHost()).getEditingDomain(), ((IHintedType)getUMLElementType(linkVISUALID)).getSemanticHint(), sourceAdapter, targetAdapter, getViewer(), getDiagramPreferencesHint(), linkdescriptor, null, semanticLink);
cc.compose(aLinkCommand);
return cc;
}
/**
* Gets the droppable element visual id.
*
* @return the droppable element visual id
* @see org.eclipse.papyrus.uml.diagram.common.editpolicies.CommonDiagramDragDropEditPolicy#getDroppableElementVisualId()
*/
@Override
protected Set<Integer> getDroppableElementVisualId() {
// TODO Auto-generated method stub
Set<Integer> elementsVisualId = new HashSet<Integer>();
elementsVisualId.add(MessageEditPart.VISUAL_ID);
elementsVisualId.add(CommentEditPartCN.VISUAL_ID);
elementsVisualId.add(ConstraintEditPartCN.VISUAL_ID);
elementsVisualId.add(LifelineEditPartCN.VISUAL_ID);
elementsVisualId.add(TimeObservationEditPartCN.VISUAL_ID);
elementsVisualId.add(DurationObservationEditPartCN.VISUAL_ID);
elementsVisualId.add(ShortCutDiagramEditPart.VISUAL_ID);
// handle nodes on messages (no visual ID detected for them)
elementsVisualId.add(-1);
return elementsVisualId;
}
/**
* @see org.eclipse.papyrus.uml.diagram.common.editpolicies.CommonDiagramDragDropEditPolicy#getDropObjectsCommand(org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest)
*
* @param dropRequest
* @return the drop command
*/
@Override
public Command getDropObjectsCommand(DropObjectsRequest dropRequest) {
ViewServiceUtil.forceLoad();
// Create a view request from the drop request and then forward getting
// the command for that.
CompositeCommand cc = new CompositeCommand("Drop"); //$NON-NLS-1$
Iterator<?> iter = dropRequest.getObjects().iterator();
if(dropRequest.getObjects().size() > 0 && dropRequest.getObjects().get(0) instanceof String) {
return getDropFileCommand(dropRequest);
}
Point location = dropRequest.getLocation().getCopy();
((GraphicalEditPart)getHost()).getContentPane().translateToRelative(location);
((GraphicalEditPart)getHost()).getContentPane().translateFromParent(location);
location.translate(((GraphicalEditPart)getHost()).getContentPane().getClientArea().getLocation().getNegated());
while(iter.hasNext()) {
EObject droppedObject = (EObject)iter.next();
int nodeVISUALID = getNodeVisualID(((IGraphicalEditPart)getHost()).getNotationView(), droppedObject);
int linkVISUALID = getLinkWithClassVisualID(droppedObject);
if(getDroppableElementVisualId().contains(nodeVISUALID) || getDroppableElementVisualId().contains(linkVISUALID)) {
dropRequest.setLocation(location);
// TODO: add to composite command ?
if(nodeVISUALID == -1 && linkVISUALID == -1 && (droppedObject instanceof Diagram)) {//if the dropped element is the diagram short cut
cc.add(new CommandProxy(dropShortCutDiagram(dropRequest, (Diagram)droppedObject, nodeVISUALID)));
} else {
cc.add(new CommandProxy(getSpecificDropCommand(dropRequest, (Element)droppedObject, nodeVISUALID, linkVISUALID)));
}
continue;
}
if(linkVISUALID == -1 && nodeVISUALID != -1) {
// The element to drop is a node
// Retrieve it's expected graphical parent
EObject graphicalParent = ((GraphicalEditPart)getHost()).resolveSemanticElement();
// Restrict the default node creation to the following cases:
// . Take the containment relationship into consideration
// . Release the constraint when GraphicalParent is a Package (Canvas for most
// diagrams)
if(graphicalParent instanceof Package) {
cc.add(getDefaultDropNodeCommand(nodeVISUALID, location, droppedObject));
} else {
if((graphicalParent instanceof Element) && ((Element)graphicalParent).getOwnedElements().contains(droppedObject)) {
cc.add(getDefaultDropNodeCommand(nodeVISUALID, location, droppedObject));
} else {
return UnexecutableCommand.INSTANCE;
}
}
} else {
if(linkVISUALID != -1) {
Collection<?> sources = linkmappingHelper.getSource((Element)droppedObject);
Collection<?> targets = linkmappingHelper.getTarget((Element)droppedObject);
if(sources.size() == 0 || targets.size() == 0) {
return UnexecutableCommand.INSTANCE;
}
// binary association
Element source = (Element)sources.toArray()[0];
Element target = (Element)targets.toArray()[0];
dropBinaryLink(cc, source, target, linkVISUALID, dropRequest.getLocation(), (Element)droppedObject);
}
}
}
return new ICommandProxy(cc);
}
}