/*****************************************************************************
* Copyright (c) 2009 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:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Adapted code from the class diagram
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.profile.custom.helper;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
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.CompartmentEditPart;
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.internal.commands.SetConnectionBendpointsCommand;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest.ConnectionViewDescriptor;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.emf.type.core.IHintedType;
import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.common.commands.DeleteLinkDuringCreationCommand;
import org.eclipse.papyrus.uml.diagram.common.commands.SemanticAdapter;
import org.eclipse.papyrus.uml.diagram.common.helper.ElementHelper;
import org.eclipse.papyrus.uml.diagram.profile.custom.commands.DependencyDiamondViewCreateCommand;
import org.eclipse.papyrus.uml.diagram.profile.custom.providers.CustomDeferredCreateConnectionViewCommand;
import org.eclipse.papyrus.uml.diagram.profile.edit.parts.DependencyBranchEditPart;
import org.eclipse.papyrus.uml.diagram.profile.edit.parts.DependencyNodeEditPart;
import org.eclipse.papyrus.uml.diagram.profile.providers.UMLElementTypes;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.UMLPackage;
/**
* The Class MultiDependencyHelper to manage adding branches or transformation of binary of n-ary
* links
*/
public class MultiDependencyHelper extends ElementHelper {
/**
* Instantiates a new multi dependency helper.
*
* @param editDomain
* the edit domain
*/
public MultiDependencyHelper(TransactionalEditingDomain editDomain) {
super();
this.editDomain = editDomain;
}
private CompoundCommand constructDependencyEnd(CompoundCommand command, DependencyDiamondViewCreateCommand nodeCreation, Collection<NamedElement> dependencyEnd, Dependency dependency, EditPartViewer viewer, PreferencesHint diagramPreferencesHint, Point location, View containerView, boolean constructSource) {
// 2. for each element create a graphical representation of the type and
// finally the branch
Iterator<NamedElement> iteratorProp = dependencyEnd.iterator();
int index = 0;
while(iteratorProp.hasNext()) {
index += 1;
// source editPart
EditPart sourceEditPart = null;
// end of the association end
NamedElement currentEnd = iteratorProp.next();
// look for if an editpart exist for this element
Collection<EditPart> editPartSet = viewer.getEditPartRegistry().values();
Iterator<EditPart> editPartIterator = editPartSet.iterator();
while(editPartIterator.hasNext() && sourceEditPart == null) {
EditPart currentEditPart = editPartIterator.next();
if((!(currentEditPart instanceof CompartmentEditPart)) && currentEditPart instanceof GraphicalEditPart && currentEnd.equals(((GraphicalEditPart)currentEditPart).resolveSemanticElement())) {
sourceEditPart = currentEditPart;
}
}
// descriptor for the branch
ConnectionViewDescriptor viewBranchDescriptor = new ConnectionViewDescriptor(UMLElementTypes.Dependency_4018, ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), diagramPreferencesHint);
// the editpart exist -> only creation of the branch
if(sourceEditPart != null) {
CustomDeferredCreateConnectionViewCommand aBranchCommand = null;
if(constructSource) {
aBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), new SemanticAdapter(null, sourceEditPart.getModel()), (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), sourceEditPart.getViewer(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewBranchDescriptor, null);
} else {
aBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), new SemanticAdapter(null, sourceEditPart.getModel()), sourceEditPart.getViewer(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewBranchDescriptor, null);
}
aBranchCommand.setElement(dependency);
(command).add(new ICommandProxy(aBranchCommand));
} else {// the editpart does not exist
// creation of the node
IAdaptable elementAdapter = new EObjectAdapter(currentEnd);
ViewDescriptor descriptor = new ViewDescriptor(elementAdapter, Node.class, null, ViewUtil.APPEND, false, diagramPreferencesHint);
// get the command and execute it.
CreateCommand nodeCreationCommand = new CreateCommand(getEditingDomain(), descriptor, containerView);
(command).add(new ICommandProxy(nodeCreationCommand));
SetBoundsCommand setBoundsCommand = new SetBoundsCommand(getEditingDomain(), "move", (IAdaptable)nodeCreationCommand.getCommandResult().getReturnValue(), new Point(location.x + 200, location.y + index * 100)); //$NON-NLS-1$
(command).add(new ICommandProxy(setBoundsCommand));
// Creation of the branch
CustomDeferredCreateConnectionViewCommand aBranchCommand = null;
if(constructSource) {
aBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), (IAdaptable)nodeCreationCommand.getCommandResult().getReturnValue(), (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), viewer, diagramPreferencesHint, viewBranchDescriptor, null);
} else {
aBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), (IAdaptable)nodeCreationCommand.getCommandResult().getReturnValue(), viewer, diagramPreferencesHint, viewBranchDescriptor, null);
}
aBranchCommand.setElement(dependency);
(command).add(new ICommandProxy(aBranchCommand));
// creation of the link
}
}
return command;
}
public Command dropMutliDependency(Dependency dependency, EditPartViewer viewer, PreferencesHint diagramPreferencesHint, Point location, View containerView) {
CompoundCommand command = new CompoundCommand();
// 0. Obtain list of property to display
ArrayList<NamedElement> endToDisplaySource = new ArrayList(dependency.getClients());
ArrayList<NamedElement> endToDisplayTarget = new ArrayList(dependency.getSuppliers());
// 1. creation of the diamond of the Dependency
DependencyDiamondViewCreateCommand nodeCreation = new DependencyDiamondViewCreateCommand(getEditingDomain(), containerView, viewer, diagramPreferencesHint, location, new SemanticAdapter(dependency, null));
command.add(new ICommandProxy(nodeCreation));
// 2. for each element create a graphical representation of the type and
// finally the branch
command = constructDependencyEnd(command, nodeCreation, endToDisplaySource, dependency, viewer, diagramPreferencesHint, location, containerView, true);
command = constructDependencyEnd(command, nodeCreation, endToDisplayTarget, dependency, viewer, diagramPreferencesHint, location, containerView, false);
return command;
}
/**
* Gets the branch dependency command.
*
* @param createConnectionViewAndElementRequest
* the create connection view and element request
* @param command
* the command
*
* @return the branch dependency command
*/
private Command getBranchDepencencyCommand(CreateConnectionViewAndElementRequest createConnectionViewAndElementRequest, Command command) {
EditPart sourceEditPart = createConnectionViewAndElementRequest.getSourceEditPart();
EditPart targetEditPart = createConnectionViewAndElementRequest.getTargetEditPart();
EObject newSemanticElement = null;
EStructuralFeature feature = null;
Dependency dependency = null;
if(((View)sourceEditPart.getModel()).getElement() != null && ((View)sourceEditPart.getModel()).getElement() instanceof Dependency) {
newSemanticElement = ((View)targetEditPart.getModel()).getElement();
dependency = (Dependency)((View)sourceEditPart.getModel()).getElement();
feature = UMLPackage.eINSTANCE.getDependency_Supplier();
}
if(((View)targetEditPart.getModel()).getElement() != null && ((View)targetEditPart.getModel()).getElement() instanceof Dependency) {
newSemanticElement = ((View)sourceEditPart.getModel()).getElement();
dependency = (Dependency)((View)targetEditPart.getModel()).getElement();
feature = UMLPackage.eINSTANCE.getDependency_Client();
}
// 0. add the branch graphically
ConnectionViewDescriptor viewDescriptor = new ConnectionViewDescriptor(UMLElementTypes.Dependency_4018, ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint());
CustomDeferredCreateConnectionViewCommand aBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), new SemanticAdapter(null, sourceEditPart.getModel()), new SemanticAdapter(null, targetEditPart.getModel()), sourceEditPart.getViewer(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
aBranchCommand.setElement(dependency);
command = new CompoundCommand();
((CompoundCommand)command).add(new ICommandProxy(aBranchCommand));
// 1. add the supplier or client
// set the new client or the new supplier
SetRequest setRequest = new SetRequest(dependency, feature, newSemanticElement);
SetValueCommand setValueCommand = new SetValueCommand(setRequest);
((CompoundCommand)command).add(new ICommandProxy(setValueCommand));
return command;
}
/**
* Gets the command.
*
* @param createConnectionViewAndElementRequest
* the create connection view and element request
* @param command
* the command
*
* @return the command
*/
public Command getCommand(CreateConnectionViewAndElementRequest createConnectionViewAndElementRequest, Command command) {
// 0. get source and target type
command = new CompoundCommand();
EditPart sourceEditPart = createConnectionViewAndElementRequest.getSourceEditPart();
EditPart targetEditPart = createConnectionViewAndElementRequest.getTargetEditPart();
// if the the source or the target is a node dependency the purpose is
// to create only one branch
if((sourceEditPart instanceof DependencyNodeEditPart) || (targetEditPart instanceof DependencyNodeEditPart)) {
return getBranchDepencencyCommand(createConnectionViewAndElementRequest, command);
}
// the source or the target has to be different of a dependency branch
if(sourceEditPart instanceof DependencyBranchEditPart) {
GraphicalEditPart dependencyNodeEditPart = lookForDependencyNodeEditPart((DependencyBranchEditPart)sourceEditPart);
if(dependencyNodeEditPart != null) {
createConnectionViewAndElementRequest.setSourceEditPart(dependencyNodeEditPart);
return getBranchDepencencyCommand(createConnectionViewAndElementRequest, command);
} else {
return UnexecutableCommand.INSTANCE;
}
}
// the source or the target has to be different of a dependency branch
if(targetEditPart instanceof DependencyBranchEditPart) {
GraphicalEditPart dependencyNodeEditPart = lookForDependencyNodeEditPart((DependencyBranchEditPart)targetEditPart);
if(dependencyNodeEditPart != null) {
createConnectionViewAndElementRequest.setTargetEditPart(dependencyNodeEditPart);
return getBranchDepencencyCommand(createConnectionViewAndElementRequest, command);
} else {
return UnexecutableCommand.INSTANCE;
}
}
// if not this a transformation of simple dependency to multiDependency
return getDependencyToMultiDependencyCommand(createConnectionViewAndElementRequest, command);
}
/**
* this method is used to create a branch of a dependency.
*
* @param createConnectionViewAndElementRequest
* the create connection view and element request
* @param command
* the command that is used to create the link branch of a dependency
*
* @return the set of command to create a branch of a dependency
*/
private Command getDependencyToMultiDependencyCommand(CreateConnectionViewAndElementRequest createConnectionViewAndElementRequest, Command command) {
// 0. creation of variables
command = new CompoundCommand();
Point sourceLocation = null;
Point targetLocation = null;
Point nodeLocation = null;
NamedElement newSemanticElement = null;// element that will be added as
// client or supplier of the dependency
EStructuralFeature feature = null; // role client or supplier
EditPart sourceEditPart = createConnectionViewAndElementRequest.getSourceEditPart();
EditPart targetEditPart = createConnectionViewAndElementRequest.getTargetEditPart();
View dependencyView = null;
Dependency dependency = null;
View parentView = null;
// ---------------------------------------------------------
// help to debug
// System.err.println("+ 0. creation of variables");
// System.err.println("+-> sourceEditpart:" + sourceEditPart);
// System.err.println("+-> targetEditPart:" + targetEditPart);
// ---------------------------------------------------------
// 1. initialization
ICommandProxy startcommand = ((ICommandProxy)createConnectionViewAndElementRequest.getStartCommand());
Iterator<?> ite = ((CompositeCommand)startcommand.getICommand()).iterator();
while(ite.hasNext()) {
ICommand currentCommand = (ICommand)ite.next();
if(currentCommand instanceof SetConnectionBendpointsCommand) {
sourceLocation = ((SetConnectionBendpointsCommand)currentCommand).getSourceRefPoint();
targetLocation = ((SetConnectionBendpointsCommand)currentCommand).getTargetRefPoint();
}
}
if(targetEditPart != null) {
// the source or the target must be a dependency
// look for the redit part that represnet the editpart
if(((View)sourceEditPart.getModel()).getElement() != null && ((View)sourceEditPart.getModel()).getElement() instanceof Dependency) {
dependencyView = ((View)sourceEditPart.getModel());
dependency = (Dependency)((View)sourceEditPart.getModel()).getElement();
nodeLocation = sourceLocation;
newSemanticElement = (NamedElement)((View)targetEditPart.getModel()).getElement();
feature = UMLPackage.eINSTANCE.getDependency_Supplier();
}
if(((View)targetEditPart.getModel()).getElement() != null && ((View)targetEditPart.getModel()).getElement() instanceof Dependency) {
dependencyView = ((View)targetEditPart.getModel());
dependency = (Dependency)((View)targetEditPart.getModel()).getElement();
nodeLocation = targetLocation;
newSemanticElement = (NamedElement)((View)sourceEditPart.getModel()).getElement();
feature = UMLPackage.eINSTANCE.getDependency_Client();
}
if(dependencyView == null) {
return null;
}
parentView = (View)dependencyView.eContainer();
// ---------------------------------------------------------
// help to debug
// System.err.println("+ 1. initialization");
// System.err.println("+-> sourceLocation:" + sourceLocation);
// System.err.println("+-> targetLocation:" + targetLocation);
// System.err.println("+-> dependencyView:" + dependencyView);
// System.err.println("+-> dependency:" + dependency);
// System.err.println("+-> nodeLocation:" + nodeLocation);
// System.err.println("+-> newSemanticElement:" + newSemanticElement);
// System.err.println("+-> feature:" + feature);
// System.err.println("+-> parentView:" + parentView);
// ---------------------------------------------------------
// 2. Remove the view of the dependency
View dependencyViewSource = ((Edge)dependencyView).getSource();
View dependencyViewTarget = ((Edge)dependencyView).getTarget();
((CompoundCommand)command).add(new ICommandProxy(new DeleteLinkDuringCreationCommand(getEditingDomain(), (Edge)dependencyView, sourceEditPart.getViewer())));
// ((CompoundCommand)command).add(new ICommandProxy(new DeleteCommand(getEditingDomain(), dependencyView)));
// ---------------------------------------------------------
// help to debug
// System.err.println("+ 2. Remove the view of the dependency");
// System.err.println("+-> command:" + command.canExecute());
// ---------------------------------------------------------
// 3. Node creation at this position
DependencyDiamondViewCreateCommand nodeCreation = new DependencyDiamondViewCreateCommand(getEditingDomain(), parentView, sourceEditPart.getViewer(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), nodeLocation, new SemanticAdapter(dependency, null));
((CompoundCommand)command).add(new ICommandProxy(nodeCreation));
// ---------------------------------------------------------
// help to debug
// System.err.println("+ 3. Node creation at this position");
// System.err.println("+-> nodeCreation:" + nodeCreation.canExecute());
// ---------------------------------------------------------
// 4. reconstruction of the old link by taking in account the old
// connection
ConnectionViewDescriptor viewDescriptor = new ConnectionViewDescriptor(UMLElementTypes.Dependency_4018, ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint());
// 5. reconstruction of the first branch between old source to node
ICommand firstBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), new SemanticAdapter(null, dependencyViewSource), (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), sourceEditPart.getViewer(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
((CustomDeferredCreateConnectionViewCommand)firstBranchCommand).setElement(dependency);
((CompoundCommand)command).add(new ICommandProxy(firstBranchCommand));
// 6. reconstruction of the second branch between node to old target
ICommand secondBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), new SemanticAdapter(null, dependencyViewTarget), sourceEditPart.getViewer(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
((CustomDeferredCreateConnectionViewCommand)secondBranchCommand).setElement(dependency);
((CompoundCommand)command).add(new ICommandProxy(secondBranchCommand));
// 7. Create of the third branch between node and target our source.
ICommand thirdBranchCommand = null;
if(dependencyView.equals((sourceEditPart.getModel()))) {
// third branch node and target
thirdBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), new SemanticAdapter(null, targetEditPart.getModel()), sourceEditPart.getViewer(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
} else {
// // third branch source and node
thirdBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Dependency_4018).getSemanticHint(), new SemanticAdapter(null, sourceEditPart.getModel()), (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), sourceEditPart.getViewer(), ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
}
((CustomDeferredCreateConnectionViewCommand)thirdBranchCommand).setElement(dependency);
((CompoundCommand)command).add(new ICommandProxy(thirdBranchCommand));
// 8. set thenew client or the new supplier
SetRequest setRequest = new SetRequest(dependency, feature, newSemanticElement);
SetValueCommand setValueCommand = new SetValueCommand(setRequest);
((CompoundCommand)command).add(new ICommandProxy(setValueCommand));
return command;
}
return null;
}
/**
* look for a dependency node from a dependency branch.
*
* @param dependencyBranchEditPart
* @return may be null
*/
protected GraphicalEditPart lookForDependencyNodeEditPart(DependencyBranchEditPart dependencyBranchEditPart) {
if(dependencyBranchEditPart.getSource() instanceof DependencyNodeEditPart) {
return (GraphicalEditPart)dependencyBranchEditPart.getSource();
}
if(dependencyBranchEditPart.getTarget() instanceof DependencyNodeEditPart) {
return (GraphicalEditPart)dependencyBranchEditPart.getTarget();
}
return null;
}
}