/*******************************************************************************
 * Copyright (c) 2011, 2012, 2013 Red Hat, Inc.
 * All rights reserved.
 * This program is 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:
 * 	Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.eclipse.bpmn2.modeler.core.features;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map.Entry;

import org.eclipse.bpmn2.Activity;
import org.eclipse.bpmn2.Association;
import org.eclipse.bpmn2.BaseElement;
import org.eclipse.bpmn2.BoundaryEvent;
import org.eclipse.bpmn2.Bpmn2Factory;
import org.eclipse.bpmn2.Collaboration;
import org.eclipse.bpmn2.ConversationLink;
import org.eclipse.bpmn2.Definitions;
import org.eclipse.bpmn2.FlowElement;
import org.eclipse.bpmn2.FlowElementsContainer;
import org.eclipse.bpmn2.FlowNode;
import org.eclipse.bpmn2.InteractionNode;
import org.eclipse.bpmn2.Lane;
import org.eclipse.bpmn2.LaneSet;
import org.eclipse.bpmn2.MessageFlow;
import org.eclipse.bpmn2.Participant;
import org.eclipse.bpmn2.Process;
import org.eclipse.bpmn2.SequenceFlow;
import org.eclipse.bpmn2.di.BPMNDiagram;
import org.eclipse.bpmn2.di.BPMNEdge;
import org.eclipse.bpmn2.di.BPMNShape;
import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesAdapter;
import org.eclipse.bpmn2.modeler.core.adapters.FeatureDescriptor;
import org.eclipse.bpmn2.modeler.core.di.DIUtils;
import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory;
import org.eclipse.bpmn2.modeler.core.utils.AnchorUtil;
import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil;
import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;
import org.eclipse.bpmn2.modeler.core.utils.GraphicsUtil;
import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
import org.eclipse.graphiti.datatypes.IDimension;
import org.eclipse.graphiti.datatypes.ILocation;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.IUpdateFeature;
import org.eclipse.graphiti.features.context.IPasteContext;
import org.eclipse.graphiti.features.context.impl.AddConnectionContext;
import org.eclipse.graphiti.features.context.impl.AddContext;
import org.eclipse.graphiti.features.context.impl.AreaContext;
import org.eclipse.graphiti.features.context.impl.UpdateContext;
import org.eclipse.graphiti.mm.algorithms.styles.Point;
import org.eclipse.graphiti.mm.pictograms.Anchor;
import org.eclipse.graphiti.mm.pictograms.Connection;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.FreeFormConnection;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.ui.editor.DiagramEditor;
import org.eclipse.graphiti.ui.features.AbstractPasteFeature;

/**
 * Default Graphiti {@code PasteFeature} class for Shapes.
 * <p>
 */
public class DefaultPasteBPMNElementFeature extends AbstractPasteFeature {

	/** The EMF Resource. */
	protected Resource resource;
	
	/** The BPMN2 Definitions object - the root element of the document. */
	protected Definitions definitions;
	
	/**
	 * Maps the ID strings of the original BPMN2 elements to their
	 * corresponding newly constructed copies.
	 */
	protected Hashtable<String, String> idMap;
	
	/** The shape map. */
	protected HashMap<ContainerShape, ContainerShape> shapeMap;
	
	/** The connection map. */
	protected HashMap<Connection, Connection> connectionMap;
	
	/** The x reference. */
	protected int xReference;
	
	/** The y reference. */
	protected int yReference;
	
	/** The diagram. */
	protected Diagram diagram;

	/**
	 * Instantiates a new default {@code PasteFeature).
	 *
	 * @param fp the Feature Provider
	 */
	public DefaultPasteBPMNElementFeature(IFeatureProvider fp) {
		super(fp);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.graphiti.features.IPasteFeature#canPaste(org.eclipse.graphiti.features.context.IPasteContext)
	 */
	@Override
	public boolean canPaste(IPasteContext context) {
		// target must be a FlowElementsContainer (Process, etc.)
		ContainerShape targetContainerShape = getTargetContainerShape(context);
		if (targetContainerShape==null)
			return false;
		BaseElement targetContainerObject = getContainerObject(targetContainerShape);
		if (targetContainerObject==null)
			return false;

		Object[] pasteObjects;
		if (context.getProperty(GraphitiConstants.COPY_FROM_CONTEXT) != null) {
			// Get objects to paste from the context. This can be used to test if
			// objects can be pasted before they have been copied to the clipboard.
			pasteObjects = context.getPictogramElements();
		}
		else {
			// can paste, if all objects on the clipboard are PictogramElements
			pasteObjects = getFromClipboard();
		}

		if (pasteObjects == null || pasteObjects.length == 0) {
			return false;
		}
		int count = 0;
		for (Object object : pasteObjects) {
			if (!(object instanceof PictogramElement)) {
				continue;
			}
			PictogramElement pe = (PictogramElement) object;
			BaseElement be = BusinessObjectUtil.getFirstBaseElement(pe);
			if (!(be instanceof FlowElement) && !(be instanceof Lane) && !(be instanceof Participant)) {
				continue;
			}
			// can't paste Boundary Events directly - these are "carried along"
			// by the Activity to which they are attached.
			if (be instanceof BoundaryEvent) {
				continue;
			}
			// can't paste Label shapes
			if (pe instanceof Shape && FeatureSupport.isLabelShape((Shape)pe)) {
				continue;
			}
			// Participants can only be pasted into into a Collaboration
			if (be instanceof Participant && !(targetContainerObject instanceof Collaboration)) {
				continue;
			}
			++count;
		}
		if (count==0)
			return false;

		return true;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.graphiti.features.IPasteFeature#paste(org.eclipse.graphiti.features.context.IPasteContext)
	 */
	@Override
	public void paste(IPasteContext context) {
		ContainerShape targetContainerShape = getTargetContainerShape(context);
		BaseElement targetContainerObject = getContainerObject(targetContainerShape);

		// save the Diagram and Resource needed for constructing the new objects
		diagram = getFeatureProvider().getDiagramTypeProvider().getDiagram();
		resource = targetContainerObject.eResource();
		definitions = ModelUtil.getDefinitions(resource);
		idMap = new Hashtable<String, String>();
		shapeMap = new HashMap<ContainerShape, ContainerShape>();
		connectionMap = new HashMap<Connection, Connection>();
		xReference = 0;
		yReference = 0;
		
		int xMin = Integer.MAX_VALUE;
		int yMin = Integer.MAX_VALUE;
		Object[] fromClipboard = getFromClipboard();
		for (Object object : fromClipboard) {
			if (object instanceof ContainerShape) {
				ILocation loc = Graphiti.getLayoutService().getLocationRelativeToDiagram((ContainerShape) object);
				if (loc.getX() < xMin) {
					xMin = loc.getX();
				}
				if (loc.getY() < yMin) {
					yMin = loc.getY();
				}
			}
		}
		if (xMin!=Integer.MAX_VALUE) {
			xReference = xMin;
			yReference = yMin;
		}

		int x = context.getX();
		int y = context.getY();
		if (!(targetContainerShape instanceof Diagram)) {
			ILocation loc = Graphiti.getLayoutService().getLocationRelativeToDiagram(targetContainerShape);
			x -= loc.getX();
			y -= loc.getY();
		}

		// First create all shapes. This creates a lookup map of old to new
		// ContainerShape objects.
		for (Object object : fromClipboard) {
			if (object instanceof ContainerShape) {
				copyShape((ContainerShape) object, targetContainerShape, x, y);
			}
		}

		// Handle connections now that we know all shapes have been created
		x = context.getX(); // Connection bendpoint coordinates are always
							// relative to diagram
		y = context.getY();
		for (Object object : fromClipboard) {
			if (object instanceof Connection) {
				copyConnection((Connection) object, targetContainerShape, x, y);
			}
		}
		
		// handle any connections that were not created because of missing source/target
		for (Entry<Connection, Connection> entry : connectionMap.entrySet()) {
			if (entry.getValue()==null) {
				copyConnection(entry.getKey(), targetContainerShape, x, y);
			}
		}
		PictogramElement newPes[] = new PictogramElement[shapeMap.size()];
		int i = 0;
		for (Entry<ContainerShape, ContainerShape> entry : shapeMap.entrySet()) {
			newPes[i++] = entry.getValue();
		}
		
		getDiagramEditor().setPictogramElementsForSelection(newPes);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.graphiti.ui.features.AbstractPasteFeature#getFromClipboard()
	 */
	protected Object[] getFromClipboard() {
		List<Object> allObjects = new ArrayList<Object>();
		Object[] objects = super.getFromClipboard();
		for (Object object : objects) {
			if (object instanceof EObject && ((EObject)object).eContainer()!=null)
				allObjects.add(object);
		}
		
		List<Object> filteredObjects = new ArrayList<Object>();
		for (Object object : allObjects) {
			if (object instanceof EObject && ((EObject)object).eContainer()!=null) {
				if (object instanceof ContainerShape) {
					filteredObjects.add(object);
				}
				else if (object instanceof Connection) {
					Connection c = (Connection)object;
					if (c.getStart()!=null && c.getEnd()!=null) {
						if (allObjects.contains(c.getStart().getParent()) &&
								allObjects.contains(c.getEnd().getParent())) {
							filteredObjects.add(object);
						}
					}
				}
			}
		}
		
		return filteredObjects.toArray();
	}

	public <T extends EObject> T copyEObject(T eObject) {
		Copier copier = new Copier() {
			
			private static final long serialVersionUID = 1L;

			@Override
			protected EObject createCopy(EObject eObject) {
				EClass eClass = getTarget(eObject.eClass());
				if (eClass.getEPackage().getEFactoryInstance() == Bpmn2Factory.eINSTANCE) {
					return Bpmn2ModelerFactory.createObject(resource, eClass);
				}
				return super.createCopy(eObject); 
			}

		};
		EObject result = copier.copy(eObject);
		copier.copyReferences();

		@SuppressWarnings("unchecked")
		T t = (T) result;
		
		// don't set a name on the new object if old object didn't have one.
		EStructuralFeature f = t.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
		if (f!=null) {
			String name = (String)eObject.eGet(f);
			if (name==null || name.isEmpty())
				t.eSet(f, null);
		}
		
		// add metadata to the ExtendedPropertiesAdapter for extension features
		ExtendedPropertiesAdapter<T> oldAdapter = ExtendedPropertiesAdapter.adapt(eObject);
		ExtendedPropertiesAdapter<T> newAdapter = ExtendedPropertiesAdapter.adapt(result);
		for (EStructuralFeature oldFeature : oldAdapter.getExtensionFeatures()) {
			FeatureDescriptor fd = newAdapter.getFeatureDescriptor(oldFeature);
			fd.setProperty(ExtendedPropertiesAdapter.IS_EXTENSION_FEATURE, Boolean.TRUE);
		}
		
		return t;
	}

	private BaseElement createNewObject(BaseElement oldObject, BaseElement targetContainerObject) {
		BaseElement newObject = null;
		try {
			Bpmn2ModelerFactory.lock();
			Bpmn2ModelerFactory.setEnableModelExtensions(false);
			newObject = copyEObject(oldObject);
		}
		finally {
			Bpmn2ModelerFactory.setEnableModelExtensions(true);
			Bpmn2ModelerFactory.unlock();
		}
		
		if (targetContainerObject instanceof Participant) {
			// need to create a Process for target container if it doesn't have one yet
			Participant participant = (Participant) targetContainerObject;
			if (participant.getProcessRef()==null) {
				Process process = Bpmn2ModelerFactory.createObject(resource, Process.class);
				participant.setProcessRef(process);
			}
			targetContainerObject = participant.getProcessRef();
		}
		
		// get rid of some of the objects created by EcoreUtil.copy() as these will be
		// constructed here because we need to create the Graphiti shapes and DI elements
		// along with these
		if (newObject instanceof FlowElementsContainer) {
			// we will create our own FlowElements, thank you!
			((FlowElementsContainer)newObject).getFlowElements().clear();
		}
		
		if (newObject instanceof Lane) {
			// we will construct these ourselves
			((Lane) newObject).getFlowNodeRefs().clear();
			((Lane) newObject).setChildLaneSet(null);
			if (targetContainerObject instanceof FlowElementsContainer) {
				FlowElementsContainer fc = (FlowElementsContainer)targetContainerObject;
				if (fc.getLaneSets().size()!=0) {
					fc.getLaneSets().get(0).getLanes().add((Lane)newObject);
				}
				else {
					LaneSet ls = Bpmn2ModelerFactory.createObject(resource, LaneSet.class);
					fc.getLaneSets().add(ls);
					ls.getLanes().add((Lane)newObject);
				}
			}
			else if (targetContainerObject instanceof Lane) {
				Lane ln = (Lane)targetContainerObject;
				if (ln.getChildLaneSet()==null) {
					LaneSet ls = Bpmn2ModelerFactory.createObject(resource, LaneSet.class);
					ln.setChildLaneSet(ls);
				}
				ln.getChildLaneSet().getLanes().add((Lane)newObject);
			}
		}
		else if (newObject instanceof FlowElement) {
			if (targetContainerObject instanceof Lane) {
				Lane ln = (Lane)targetContainerObject;
				targetContainerObject = getFlowElementsContainer(ln);
				// newObject could be either a Shape (FlowNode) or a Connection;
				// only add FlowNodes to the Lane's FlowNodeRefs list.
				if (newObject instanceof FlowNode)
					ln.getFlowNodeRefs().add((FlowNode)newObject);
			}
			if (targetContainerObject instanceof FlowElementsContainer) {
				((FlowElementsContainer)targetContainerObject).getFlowElements().add((FlowElement) newObject);
			}
		}
		else if (newObject instanceof Participant) {
			Participant participant = (Participant)newObject;
			if (((Participant) newObject).getProcessRef()!=null) {
				// need to create a new Process for this thing
				Process process = Bpmn2ModelerFactory.createObject(resource, Process.class);
				participant.setProcessRef(process);
			}
			if (targetContainerObject instanceof Collaboration) {
				Collaboration collab = (Collaboration)targetContainerObject;
				collab.getParticipants().add((Participant)newObject);
			}
		}

		// Ensure IDs are unique
		setId(newObject);

		TreeIterator<EObject> iter = newObject.eAllContents();
		while (iter.hasNext()) {
			EObject newChild = iter.next();
			setId(newChild);
		}

		for (EReference ref : newObject.eClass().getEAllReferences()) {
			if (!ref.isContainment()) {
				Object oldValue = oldObject.eGet(ref);
				// TODO: do we need this?
				// this mess also duplicates "incoming" and "outgoing" (for SequenceFlows)
				// which are already being handled in copyConnection()...
//				if (oldValue instanceof EObjectEList) {
//					EObjectEList oldList = (EObjectEList)oldObject.eGet(ref);
//					EObjectEList newList = (EObjectEList)newObject.eGet(ref);
//					for (Object oldRefObject : oldList) {
//						if (oldRefObject instanceof EObject) {
//							String oldId = getId((EObject)oldRefObject);
//							if (oldId!=null) {
//								String newId = idMap.get(oldId);
//								EObject newRefObject = findObjectById(newId);
//								newList.add(newRefObject);
//							}
//						}
//					}
//				}
//				else
				if (oldValue instanceof EObject){
					EObject oldRefObject = (EObject)oldValue;
					String oldId = getId(oldRefObject);
					if (oldId!=null) {
						String newId = idMap.get(oldId);
						if (newId!=null) {
							EObject newRefObject = findObjectById(newId);
							newObject.eSet(ref, newRefObject);
						}
						else if (newObject.eGet(ref) != null){
							EObject newRefObject = (EObject) newObject.eGet(ref);
							newId = getId(newRefObject);
							if (newId!=null)
								idMap.put(oldId, newId);
						}
					}
				}
			}
		}
		return newObject;
	}

	private String getId(EObject newObject) {
		EStructuralFeature feature = newObject.eClass().getEStructuralFeature("id"); //$NON-NLS-1$
		if (feature != null) {
			return (String) newObject.eGet(feature);
		}
		return null;
	}
	
	private String setId(EObject newObject) {
		String newId = null;
		String oldId = null;
		EStructuralFeature feature = newObject.eClass().getEStructuralFeature("id"); //$NON-NLS-1$
		if (feature != null) {
			oldId = (String) newObject.eGet(feature);
			if (idMap.contains(oldId)) {
				newId = idMap.get(oldId);
				newObject.eSet(feature, newId);
			}
			else {
				newObject.eUnset(feature);
				newId = ModelUtil.setID(newObject);
				idMap.put(oldId, newId);
			}
		}
		return oldId;
	}

	private boolean wasCopied(EObject object) {
		String id = getId(object);
		if (id!=null) {
			return idMap.containsValue(id);
		}
		return false;
	}
	
	private EObject findObjectById(String id) {
		TreeIterator<EObject> iter = definitions.eAllContents();
		while (iter.hasNext()) {
			EObject o = iter.next();
			EStructuralFeature feature = o.eClass().getEStructuralFeature("id"); //$NON-NLS-1$
			if (feature != null) {
				String thisId = (String) o.eGet(feature);
				if (thisId != null && !thisId.isEmpty() && thisId.equals(id))
					return o;
			}
		}
		return null;
	}

	private ContainerShape findShape(EObject object) {
		List<PictogramElement> pes = Graphiti.getLinkService().getPictogramElements(diagram, object);
		for (PictogramElement pe : pes) {
			if (pe instanceof ContainerShape)
				return (ContainerShape) pe;
		}
		return null;
	}

	private Connection findConnection(EObject object) {
		List<PictogramElement> pes = Graphiti.getLinkService().getPictogramElements(diagram, object);
		for (PictogramElement pe : pes) {
			if (pe instanceof Connection)
				return (Connection) pe;
		}
		return null;
	}

	private BaseElement copyShape(ContainerShape oldShape, ContainerShape targetContainerShape, int x, int y) {
		if (shapeMap.get(oldShape)!=null)
			return null;
		
		BaseElement targetContainerObject = getContainerObject(targetContainerShape);
		BaseElement oldObject = BusinessObjectUtil.getFirstBaseElement(oldShape);
		BaseElement newObject = createNewObject(oldObject, targetContainerObject);

		AddContext ac = new AddContext(new AreaContext(), newObject);
		ILocation loc = Graphiti.getLayoutService().getLocationRelativeToDiagram(oldShape);
		IDimension size = GraphicsUtil.calculateSize(oldShape);
		// The default Add BPMN Shape feature will position the new shape so its
		// center is at the target location; for copy/paste we want to use the
		// top-left corner instead so that copied connection bendpoints (if any)
		// line up properly.
		int deltaX = 0;
		int deltaY = 0;
		if (oldObject instanceof FlowNode) {
			deltaX = loc.getX() - xReference + size.getWidth() / 2;
			deltaY = loc.getY() - yReference + size.getHeight() / 2;
		}
		ac.setLocation(x + deltaX, y + deltaY);
		ac.setSize(size.getWidth(), size.getHeight());
		ac.setTargetContainer(targetContainerShape);

		BPMNShape oldBpmnShape = null;
		if (oldObject instanceof BaseElement) {
			BPMNDiagram bpmnDiagram = DIUtils.findBPMNDiagram(oldShape);
			oldBpmnShape = DIUtils.findBPMNShape(bpmnDiagram, (BaseElement)oldObject);
			ac.putProperty(GraphitiConstants.COPIED_BPMN_DI_ELEMENT, oldBpmnShape);
		}
		ac.putProperty(GraphitiConstants.COPIED_BPMN_OBJECT, oldObject);
		
		
		ContainerShape newShape = (ContainerShape) getFeatureProvider().addIfPossible(ac);

		shapeMap.put(oldShape, newShape);

		if (oldObject instanceof Participant) {
			// copy the contained Process elements
			oldObject = ((Participant)oldObject).getProcessRef();
		}

		// create shapes and connections for children if this is a FlowElementsContainer
		if (oldObject instanceof FlowElementsContainer) {
			List<ContainerShape> childShapes = new ArrayList<ContainerShape>();
			List<Connection> childConnections = new ArrayList<Connection>();
			TreeIterator<EObject> iter = oldObject.eAllContents();
			while (iter.hasNext()) {
				// look up the old child object that corresponds to the new child object 
				EObject oldChildObject = iter.next();
				if (oldChildObject instanceof BoundaryEvent) {
					// Defer Boundary Event creation until we're sure that the
					// new attachedToRef task is actually created.
					continue;
				}
				if (wasCopied(oldChildObject)) {
					// stop infinite recursion: this would happen if a FlowElementsContainer
					//was copied into itself.
					continue;
				}
				
				// if the old child has a Graphiti ContainerShape, duplicate it.
				ContainerShape oldChildShape = findShape(oldChildObject);
				if (oldChildShape != null) {
					childShapes.add(oldChildShape);
				}
				Connection oldChildConnection = findConnection(oldChildObject);
				if (oldChildConnection != null) {
					childConnections.add(oldChildConnection);
				}
			}
			
			for (ContainerShape oldChildShape : childShapes) {
				copyShape(oldChildShape, newShape, 0, 0);
			}
			
			for (Connection oldChildConnection : childConnections) {
				copyConnection(oldChildConnection, newShape, x, y);
			}
		}
		else if (oldObject instanceof Lane) {
	        List<PictogramElement> shapes = new ArrayList<PictogramElement>();
	        Lane oldLane = (Lane)oldObject;
	        if (oldLane.getChildLaneSet()!=null) {
	        	for (Lane oldChildLaneObject : oldLane.getChildLaneSet().getLanes()) {
	        		ContainerShape oldChildLaneShape = findShape(oldChildLaneObject);
	        		if (oldChildLaneShape != null) {
	        			copyShape(oldChildLaneShape, newShape, 0, 0);
	        		}
	        	}
	        }
			for (FlowNode oldChildObject : oldLane.getFlowNodeRefs()) {
				ContainerShape oldChildShape = findShape(oldChildObject);
				if (oldChildShape != null) {
					copyShape(oldChildShape, newShape, 0, 0);
					shapes.add(oldChildShape);
				}
			}
			List<Connection> connections = DefaultCopyBPMNElementFeature.findAllConnections(shapes);
			for (Connection oldChildConnection : connections) {
				copyConnection(oldChildConnection, newShape, x, y);
			}
		}
		
		// also copy the BPMNShape properties
		if (oldBpmnShape!=null) {
			BPMNShape newBpmnShape = DIUtils.findBPMNShape((BaseElement)newObject);
			newBpmnShape.setIsExpanded(oldBpmnShape.isIsExpanded());
			newBpmnShape.setIsHorizontal(oldBpmnShape.isIsHorizontal());
			newBpmnShape.setIsMarkerVisible(oldBpmnShape.isIsMarkerVisible());
			newBpmnShape.setIsMessageVisible(oldBpmnShape.isIsMessageVisible());
			newBpmnShape.setParticipantBandKind(oldBpmnShape.getParticipantBandKind());
		}

		UpdateContext uc = new UpdateContext(newShape);
		IUpdateFeature uf = getFeatureProvider().getUpdateFeature(uc);
		// force an update to cause the newly created ContainerShape to be rendered properly
		uc.putProperty(GraphitiConstants.FORCE_UPDATE_ALL, Boolean.TRUE);
		uf.update(uc);
		
		if (newObject instanceof Activity) {
			// copy the Activity's Boundary Events if it has any
			TreeIterator<EObject> i = definitions.eAllContents();
			while (i.hasNext()) {
				EObject o = i.next();
				if (o instanceof BoundaryEvent) {
					BoundaryEvent oldBeObject = (BoundaryEvent)o;
					if (oldBeObject.getAttachedToRef() == oldObject) {
						// here's one...
						ContainerShape oldBeShape = findShape(oldBeObject);
						copyShape(oldBeShape, targetContainerShape, x, y);
					}
				}
			}
		}

		return newObject;
	}

	private BaseElement copyConnection(Connection oldConnection, ContainerShape targetContainerShape, int x, int y) {
		if (connectionMap.get(oldConnection)!=null)
			return null;
		
		BaseElement targetContainerObject = getContainerObject(targetContainerShape);
		BaseElement oldObject = BusinessObjectUtil.getFirstBaseElement(oldConnection);
		BaseElement newObject = createNewObject(oldObject, targetContainerObject);

		Anchor oldStart = oldConnection.getStart();
		Anchor oldEnd = oldConnection.getEnd();
		ContainerShape newSource = shapeMap.get(oldStart.getParent());
		ContainerShape newTarget = shapeMap.get(oldEnd.getParent());
		if (newSource==null || newTarget==null) {
			// source or target does not exist yet - handle this connection later
			connectionMap.put(oldConnection, null);
			return null;
		}
		
		Anchor newStart;
		Anchor newEnd;
		ILocation loc = Graphiti.getLayoutService().getLocationRelativeToDiagram(oldStart);
		newStart = AnchorUtil.createAnchor(newSource, loc.getX(), loc.getY());

		loc = Graphiti.getLayoutService().getLocationRelativeToDiagram(oldEnd);
		newEnd = AnchorUtil.createAnchor(newTarget, loc.getX(), loc.getY());

		BaseElement newSourceObject = BusinessObjectUtil.getFirstBaseElement(newSource);
		BaseElement newTargetObject = BusinessObjectUtil.getFirstBaseElement(newTarget);
		if (newObject instanceof SequenceFlow) {
			((SequenceFlow) newObject).setSourceRef((FlowNode) newSourceObject);
			((SequenceFlow) newObject).setTargetRef((FlowNode) newTargetObject);
		}
		else if (newObject instanceof Association) {
			((Association) newObject).setSourceRef((FlowNode) newSourceObject);
			((Association) newObject).setTargetRef((FlowNode) newTargetObject);
		}
		else if (newObject instanceof MessageFlow) {
			((MessageFlow) newObject).setSourceRef((InteractionNode) newSourceObject);
			((MessageFlow) newObject).setTargetRef((InteractionNode) newTargetObject);
		}
		else if (newObject instanceof ConversationLink) {
			((ConversationLink) newObject).setSourceRef((InteractionNode) newSourceObject);
			((ConversationLink) newObject).setTargetRef((InteractionNode) newTargetObject);
		}
		AddConnectionContext acc = new AddConnectionContext(newStart, newEnd);
		acc.setNewObject(newObject);

		Connection newConnection = (Connection) getFeatureProvider().addIfPossible(acc);
		connectionMap.put(oldConnection, newConnection);

		if (oldConnection instanceof FreeFormConnection && newConnection instanceof FreeFormConnection) {
			for (Point p : ((FreeFormConnection) oldConnection).getBendpoints()) {
				int deltaX = p.getX() - xReference;
				int deltaY = p.getY() - yReference;
				Point newPoint = GraphicsUtil.createPoint(x + deltaX, y + deltaY);
				((FreeFormConnection) newConnection).getBendpoints().add(newPoint);
			}
		}
		
		// also copy the BPMNEdge properties
		if (oldObject instanceof BaseElement) {
			BPMNDiagram bpmnDiagram = DIUtils.findBPMNDiagram(oldConnection);
			BPMNEdge oldBpmnEdge = DIUtils.findBPMNEdge(bpmnDiagram, (BaseElement)oldObject);
			if (oldBpmnEdge!=null) {
				bpmnDiagram = DIUtils.findBPMNDiagram(newConnection);
				BPMNEdge newBpmnEdge = DIUtils.findBPMNEdge(bpmnDiagram, (BaseElement)newObject);
				newBpmnEdge.setMessageVisibleKind(oldBpmnEdge.getMessageVisibleKind());
			}
		}

		FeatureSupport.updateConnection(getFeatureProvider(), newConnection);

		return newObject;
	}
	
	private ContainerShape getTargetContainerShape(IPasteContext context) {
		Diagram diagram = getFeatureProvider().getDiagramTypeProvider().getDiagram();
		
		Point p = GraphicsUtil.createPoint(context.getX(), context.getY());
		Shape s = GraphicsUtil.findShapeAt(diagram, p, new GraphicsUtil.IShapeFilter() {
			@Override
			public boolean matches(Shape shape) {
				if (shape instanceof ContainerShape) {
					BaseElement be = getContainerObject((ContainerShape) shape);
					return be instanceof FlowElementsContainer || be instanceof Participant;
				}
				return false;
			}
		});
		if (s!=null)
			return (ContainerShape) s;
		return diagram;
	}
	
	private BaseElement getContainerObject(ContainerShape targetContainerShape) {
		EObject bo = BusinessObjectUtil.getBusinessObjectForPictogramElement(targetContainerShape);
		if (bo instanceof BPMNDiagram) {
			bo = ((BPMNDiagram) bo).getPlane().getBpmnElement();
		}
		if (bo instanceof Participant) {
			if (!FeatureSupport.isChoreographyParticipantBand(targetContainerShape))
				return (Participant) bo;
			bo = ((Participant) bo).getProcessRef();
		}
		if (bo instanceof FlowElementsContainer || bo instanceof Lane || bo instanceof Collaboration)
			return (BaseElement) bo;
		return null;
	}
	
	private FlowElementsContainer getFlowElementsContainer(Lane lane) {
		EObject container = lane.eContainer();
		while (!(container instanceof FlowElementsContainer) && container!=null)
			container = container.eContainer();
		return (FlowElementsContainer)container;
	}
	
	protected DiagramEditor getDiagramEditor() {
		return (DiagramEditor)getFeatureProvider().getDiagramTypeProvider().getDiagramBehavior().getDiagramContainer();
	}
}
