/*****************************************************************************
* Copyright (c) 2011 CEA LIST.
*
*
* 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:
* Amine EL KOUHEN (CEA LIST/INRIA DaRT) amine.el_kouhen@inria.fr
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.deployment.custom.edit.policies;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
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.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.requests.ChangeBoundsRequest;
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.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
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.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.common.editpolicies.OldCommonDiagramDragDropEditPolicy;
import org.eclipse.papyrus.uml.diagram.deployment.custom.edit.command.CreateViewCommand;
import org.eclipse.papyrus.uml.diagram.deployment.custom.edit.helpers.DeploymentLinkMappingHelper;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.ArtifactEditPart;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.ArtifactEditPartACN;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.ArtifactEditPartCN;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.CommentEditPart;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.ConstraintEditPart;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.DependencyEditPart;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.DeviceEditPart;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.DeviceEditPartCN;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.ExecutionEnvironmentEditPart;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.ExecutionEnvironmentEditPartCN;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.NodeEditPart;
import org.eclipse.papyrus.uml.diagram.deployment.edit.parts.NodeEditPartCN;
import org.eclipse.papyrus.uml.diagram.deployment.part.UMLVisualIDRegistry;
import org.eclipse.papyrus.uml.diagram.deployment.providers.UMLElementTypes;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Collaboration;
import org.eclipse.uml2.uml.CollaborationUse;
import org.eclipse.uml2.uml.ConnectableElement;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Port;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.StructuredClassifier;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.TypedElement;
// TODO: Auto-generated Javadoc
/**
* This class provides an implementation for specific behavior of Drag and Drop in the Composite Diagram.
*/
public class CustomDiagramDragDropEditPolicy extends OldCommonDiagramDragDropEditPolicy {
/**
* Default constructor.
*/
public CustomDiagramDragDropEditPolicy() {
super(DeploymentLinkMappingHelper.getInstance());
}
/**
* Gets the droppable element visual id.
*
* @return the droppable element visual id {@inheritDoc}
*/
@Override
protected Set<Integer> getDroppableElementVisualId() {
// TopLevelNodes
Set<Integer> droppableElementsVisualId = new HashSet<Integer>();
droppableElementsVisualId.add(NodeEditPart.VISUAL_ID);
droppableElementsVisualId.add(DeviceEditPart.VISUAL_ID);
droppableElementsVisualId.add(ExecutionEnvironmentEditPart.VISUAL_ID);
droppableElementsVisualId.add(ArtifactEditPart.VISUAL_ID);
droppableElementsVisualId.add(CommentEditPart.VISUAL_ID);
droppableElementsVisualId.add(ConstraintEditPart.VISUAL_ID);
// Class CN
droppableElementsVisualId.add(ArtifactEditPartCN.VISUAL_ID);
droppableElementsVisualId.add(ArtifactEditPartACN.VISUAL_ID);
droppableElementsVisualId.add(NodeEditPartCN.VISUAL_ID);
droppableElementsVisualId.add(DeviceEditPartCN.VISUAL_ID);
droppableElementsVisualId.add(ExecutionEnvironmentEditPartCN.VISUAL_ID);
return droppableElementsVisualId;
}
/**
* 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);
}
/**
* Gets the specific drop command.
*
* @param dropRequest
* the drop request
* @param semanticElement
* the semantic element
* @param nodeVISUALID
* the node visualid
* @param linkVISUALID
* the link visualid
* @return the specific drop command {@inheritDoc}
*/
@Override
protected Command getSpecificDropCommand(DropObjectsRequest dropRequest, Element semanticElement, int nodeVISUALID, int linkVISUALID) {
// Switch test over linkVisualID
switch(linkVISUALID) {
case DependencyEditPart.VISUAL_ID:
return dropDependency(dropRequest, semanticElement, linkVISUALID);
default:
// Switch test over nodeVISUALID
switch(nodeVISUALID) {
// Test TopLevelNode... Start
case NodeEditPart.VISUAL_ID:
case DeviceEditPart.VISUAL_ID:
case ExecutionEnvironmentEditPart.VISUAL_ID:
case ArtifactEditPart.VISUAL_ID:
return dropTopLevelNode(dropRequest, semanticElement, nodeVISUALID, linkVISUALID);
// Test TopLevelNode... End
case CommentEditPart.VISUAL_ID:
case ConstraintEditPart.VISUAL_ID:
default:
return super.getSpecificDropCommand(dropRequest, semanticElement, nodeVISUALID, linkVISUALID);
}
}
}
/**
* Returns the drop command for Dependency links.
*
* @param dropRequest
* the drop request
* @param semanticLink
* the element to drop
* @param linkVISUALID
* the visual identifier of the EditPart of the dropped element
* @return the drop command
*/
protected Command dropDependency(DropObjectsRequest dropRequest, Element semanticLink, int linkVISUALID) {
Collection<?> sourceEnds = DeploymentLinkMappingHelper.getInstance().getSource(semanticLink);
Collection<?> targetEnds = DeploymentLinkMappingHelper.getInstance().getTarget(semanticLink);
// Dependency with Unary ends
if((sourceEnds != null) && (targetEnds != null) && (sourceEnds.size() == 1) && (targetEnds.size() == 1)) {
Element source = (Element)sourceEnds.toArray()[0];
Element target = (Element)targetEnds.toArray()[0];
return new ICommandProxy(dropBinaryLink(new CompositeCommand("drop Dependency"), source, target, //$NON-NLS-1$
linkVISUALID, dropRequest.getLocation(), semanticLink));
} else {
return UnexecutableCommand.INSTANCE;
}
}
/**
* Returns the drop command for Property 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 dropProperty(DropObjectsRequest dropRequest, Property droppedElement, int nodeVISUALID) {
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
// Default drop location
Point location = dropRequest.getLocation().getCopy();
// Port inherits from Property this case should be excluded and treated
// separately
if(!(droppedElement instanceof Port)) {
if((graphicalParentObject instanceof Classifier) && (((Classifier)graphicalParentObject).getAllAttributes().contains(droppedElement))) {
// The graphical parent is the real owner of the dropped
// property.
// The dropped property may also be an inherited attribute of
// the graphical parent.
return new ICommandProxy(getDefaultDropNodeCommand(nodeVISUALID, location, droppedElement));
} else if(graphicalParentObject instanceof ConnectableElement) {
Type type = ((ConnectableElement)graphicalParentObject).getType();
if((type != null) && (type instanceof Classifier) && (((Classifier)type).getAllAttributes().contains(droppedElement))) {
// The graphical parent is a Property typed by a Classifier
// that owns or inherits the
// dropped property.
return new ICommandProxy(getDefaultDropNodeCommand(nodeVISUALID, location, droppedElement));
}
}
}
return UnexecutableCommand.INSTANCE;
}
/**
* <pre>
* This method return a drop command for TopLevelNode.
* 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
* @param linkVISUALID
* the visual identifier of the EditPart of the dropped element
* @return the drop command
*/
protected Command dropTopLevelNode(DropObjectsRequest dropRequest, Element semanticElement, int nodeVISUALID, int linkVISUALID) {
GraphicalEditPart graphicalParentEditPart = (GraphicalEditPart)getHost();
EObject graphicalParentObject = graphicalParentEditPart.resolveSemanticElement();
if(graphicalParentObject instanceof org.eclipse.uml2.uml.Package) {
return new ICommandProxy(getDefaultDropNodeCommand(nodeVISUALID, dropRequest.getLocation(), semanticElement));
}
return UnexecutableCommand.INSTANCE;
}
/**
* <pre>
* This method returns the drop command for AffixedNode (Port, Parameter)
* in case the node is dropped on a ShapeCompartmentEditPart.
* </pre>
*
* @param nodeVISUALID
* the node visual identifier
* @param location
* the drop location
* @param droppedObject
* the object to drop
* @return a CompositeCommand for Drop
*/
protected CompoundCommand getDropAffixedNodeInCompartmentCommand(int nodeVISUALID, Point location, EObject droppedObject) {
CompoundCommand cc = new CompoundCommand("Drop");
IAdaptable elementAdapter = new EObjectAdapter(droppedObject);
ViewDescriptor descriptor = new ViewDescriptor(elementAdapter, Node.class, ((IHintedType)getUMLElementType(nodeVISUALID)).getSemanticHint(), ViewUtil.APPEND, false, getDiagramPreferencesHint());
// Create the command targeting host parent (owner of the
// ShapeCompartmentEditPart)
CreateViewCommand createCommand = new CreateViewCommand(getEditingDomain(), descriptor, ((View)(getHost().getParent().getModel())));
cc.add(new ICommandProxy(createCommand));
SetBoundsCommand setBoundsCommand = new SetBoundsCommand(getEditingDomain(), "move", (IAdaptable)createCommand.getCommandResult().getReturnValue(), location);
cc.add(new ICommandProxy(setBoundsCommand));
return cc;
}
/**
* Avoid dropped element to get orphaned for DND action resulting in a specific action (not a move).
*
* @param request
* the request
* @return the drag command
*/
@Override
protected Command getDragCommand(ChangeBoundsRequest request) {
Boolean isSpecificDrag = false;
Iterator<?> iter = request.getEditParts().iterator();
EObject graphicalParentObject = ((GraphicalEditPart)getHost()).resolveSemanticElement();
while((graphicalParentObject != null) && (iter.hasNext())) {
EObject droppedObject = null;
EditPart droppedEditPart = (EditPart)iter.next();
if(droppedEditPart instanceof GraphicalEditPart) {
droppedObject = ((GraphicalEditPart)droppedEditPart).resolveSemanticElement();
}
isSpecificDrag = isSpecificDropActionExpected((GraphicalEditPart)getHost(), droppedObject);
}
if(isSpecificDrag) {
return null;
}
return super.getDragCommand(request);
}
/**
* @see org.eclipse.gmf.runtime.diagram.ui.editpolicies.DiagramDragDropEditPolicy#getDropCommand(org.eclipse.gef.requests.ChangeBoundsRequest)
* @param request
* @return
*/
@Override
protected Command getDropCommand(ChangeBoundsRequest request) {
Boolean isSpecificDrop = false;
Iterator<?> iter = request.getEditParts().iterator();
EObject graphicalParentObject = ((GraphicalEditPart)getHost()).resolveSemanticElement();
while((graphicalParentObject != null) && (iter.hasNext())) {
EObject droppedObject = null;
EditPart droppedEditPart = (EditPart)iter.next();
if(droppedEditPart instanceof GraphicalEditPart) {
droppedObject = ((GraphicalEditPart)droppedEditPart).resolveSemanticElement();
}
isSpecificDrop = isSpecificDropActionExpected((GraphicalEditPart)getHost(), droppedObject);
}
if(isSpecificDrop) {
return getDropObjectsCommand(castToDropObjectsRequest(request));
}
return super.getDropCommand(request);
}
/**
* Test if a specific drop action shall is expected.
*
* @param graphicalParent
* the graphical parent
* @param droppedObject
* the dropped object
* @return true, if is specific drop action expected
*/
protected boolean isSpecificDropActionExpected(GraphicalEditPart graphicalParent, EObject droppedObject) {
boolean isSpecificDropActionExpected = false;
EObject graphicalParentObject = graphicalParent.resolveSemanticElement();
if(graphicalParentObject != null) {
if(graphicalParentObject instanceof Collaboration) {
if((droppedObject instanceof Collaboration) || (droppedObject instanceof Class)) {
isSpecificDropActionExpected = true;
}
} else if(graphicalParentObject instanceof StructuredClassifier) {
if((droppedObject instanceof Collaboration) || (droppedObject instanceof Class)) {
isSpecificDropActionExpected = true;
}
} else if(graphicalParentObject instanceof TypedElement) {
if(droppedObject instanceof Type) {
isSpecificDropActionExpected = true;
}
} else if(graphicalParentObject instanceof CollaborationUse) {
if(droppedObject instanceof Collaboration) {
isSpecificDropActionExpected = true;
}
}
}
return isSpecificDropActionExpected;
}
}