Fix some bugs with copy/paste for Pools, Lanes and SubProcesses
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIUtils.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIUtils.java
index b95ec8e..7db2963 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIUtils.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/DIUtils.java
@@ -13,7 +13,11 @@
package org.eclipse.bpmn2.modeler.core.di;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.eclipse.bpmn2.Association;
import org.eclipse.bpmn2.BaseElement;
@@ -47,6 +51,7 @@
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.util.EcoreUtil.UsageCrossReferencer;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.graphiti.datatypes.IDimension;
@@ -573,14 +578,16 @@
*/
public static BPMNShape findBPMNShape(BaseElement baseElement) {
Definitions definitions = ModelUtil.getDefinitions(baseElement);
- for (BPMNDiagram d : definitions.getDiagrams()) {
- BPMNDiagram bpmnDiagram = (BPMNDiagram)d;
- BaseElement bpmnElement = null;
- for (DiagramElement de : bpmnDiagram.getPlane().getPlaneElement()) {
- if (de instanceof BPMNShape) {
- bpmnElement = ((BPMNShape)de).getBpmnElement();
- if (bpmnElement == baseElement)
- return (BPMNShape)de;
+ if (definitions!=null) {
+ for (BPMNDiagram d : definitions.getDiagrams()) {
+ BPMNDiagram bpmnDiagram = (BPMNDiagram)d;
+ BaseElement bpmnElement = null;
+ for (DiagramElement de : bpmnDiagram.getPlane().getPlaneElement()) {
+ if (de instanceof BPMNShape) {
+ bpmnElement = ((BPMNShape)de).getBpmnElement();
+ if (bpmnElement == baseElement)
+ return (BPMNShape)de;
+ }
}
}
}
@@ -648,7 +655,14 @@
BPMNDiagram bpmnDiagram = DIUtils.findBPMNDiagram(rootElement);
RootElement newRootElement = null;
if (bpmnDiagram==null) {
- canDelete = true;
+ List<EObject> allObjects = new ArrayList<EObject>();
+ Map<EObject, Collection<EStructuralFeature.Setting>> usages;
+ TreeIterator<EObject> iter = rootElement.eContainer().eAllContents();
+ while (iter.hasNext())
+ allObjects.add(iter.next());
+
+ usages = UsageCrossReferencer.findAll(allObjects, rootElement);
+ canDelete = usages.isEmpty();
}
else {
// find a replacement for the BPMNDiagram target element
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultConnectionRouter.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultConnectionRouter.java
index 50fac05..ebb0c69 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultConnectionRouter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultConnectionRouter.java
@@ -18,13 +18,13 @@
import java.util.List;
import org.eclipse.bpmn2.BaseElement;
+import org.eclipse.bpmn2.FlowElementsContainer;
import org.eclipse.bpmn2.Lane;
import org.eclipse.bpmn2.di.BPMNShape;
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.GraphicsUtil.LineSegment;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.graphiti.features.IFeatureProvider;
@@ -34,12 +34,9 @@
import org.eclipse.graphiti.features.context.impl.AddConnectionContext;
import org.eclipse.graphiti.features.context.impl.DeleteContext;
import org.eclipse.graphiti.features.impl.AbstractAddShapeFeature;
-import org.eclipse.graphiti.mm.MmFactory;
-import org.eclipse.graphiti.mm.Property;
import org.eclipse.graphiti.mm.algorithms.Polyline;
import org.eclipse.graphiti.mm.algorithms.styles.LineStyle;
import org.eclipse.graphiti.mm.algorithms.styles.Point;
-import org.eclipse.graphiti.mm.impl.PropertyImpl;
import org.eclipse.graphiti.mm.pictograms.Anchor;
import org.eclipse.graphiti.mm.pictograms.Connection;
import org.eclipse.graphiti.mm.pictograms.ConnectionDecorator;
@@ -210,9 +207,18 @@
if (allShapes==null)
findAllShapes();
for (ContainerShape shape : allShapes) {
- if (!FeatureSupport.isGroupShape(shape) && !FeatureSupport.isLabelShape(shape) && !FeatureSupport.isParticipant(shape))
+ if (!FeatureSupport.isGroupShape(shape) && !FeatureSupport.isLabelShape(shape) && !FeatureSupport.isParticipant(shape)) {
+ EObject bo = BusinessObjectUtil.getBusinessObjectForPictogramElement(shape);
+ if (bo instanceof FlowElementsContainer) {
+ // it's not a collision if the shape is a SubProcess and
+ // both source and target connection points lie inside the SubProcess
+ if (GraphicsUtil.contains(shape, p1) || GraphicsUtil.contains(shape, p2))
+ continue;
+ }
+
if (GraphicsUtil.intersectsLine(shape, p1, p2))
collisions.add(shape);
+ }
}
// if (collisions.size()>0)
// GraphicsUtil.dump("Collisions with line ["+p1.getX()+", "+p1.getY()+"]"+" ["+p2.getX()+", "+p2.getY()+"]", collisions);
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultPasteBPMNElementFeature.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultPasteBPMNElementFeature.java
index 5fd2d93..9ad91cf 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultPasteBPMNElementFeature.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/DefaultPasteBPMNElementFeature.java
@@ -21,7 +21,7 @@
import org.eclipse.bpmn2.Association;
import org.eclipse.bpmn2.BaseElement;
import org.eclipse.bpmn2.BoundaryEvent;
-import org.eclipse.bpmn2.Bpmn2Package;
+import org.eclipse.bpmn2.Bpmn2Factory;
import org.eclipse.bpmn2.Collaboration;
import org.eclipse.bpmn2.ConversationLink;
import org.eclipse.bpmn2.Definitions;
@@ -46,24 +46,25 @@
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.GraphicsUtil.IShapeFilter;
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;
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.IAddFeature;
+import org.eclipse.graphiti.features.ICreateConnectionFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.IUpdateFeature;
+import org.eclipse.graphiti.features.context.ICreateConnectionContext;
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.CreateConnectionContext;
import org.eclipse.graphiti.features.context.impl.UpdateContext;
import org.eclipse.graphiti.mm.algorithms.styles.Point;
import org.eclipse.graphiti.mm.pictograms.Anchor;
@@ -164,6 +165,10 @@
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)
@@ -281,12 +286,42 @@
return filteredObjects.toArray();
}
-
+
+ public <T extends EObject> T copyEObject(T eObject) {
+ Copier copier = new Copier() {
+ @Override
+ protected EObject createCopy(EObject eObject) {
+ EClass eClass = getTarget(eObject.eClass());
+ if (eClass.getEPackage().getEFactoryInstance() == Bpmn2Factory.eINSTANCE) {
+ return Bpmn2ModelerFactory.create(resource, eClass);
+ }
+ return super.createCopy(eObject);
+ }
+
+ };
+ EObject result = copier.copy(eObject);
+ copier.copyReferences();
+
+ @SuppressWarnings("unchecked")
+ T t = (T) result;
+ return t;
+ }
+
private BaseElement createNewObject(BaseElement oldObject, BaseElement targetContainerObject) {
Bpmn2ModelerFactory.setEnableModelExtensions(false);
- BaseElement newObject = EcoreUtil.copy(oldObject);
+ BaseElement newObject = copyEObject(oldObject);
Bpmn2ModelerFactory.setEnableModelExtensions(true);
+ 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.create(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
@@ -424,6 +459,14 @@
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()) {
@@ -500,6 +543,8 @@
// 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
@@ -509,24 +554,29 @@
// 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) {
- copyShape(oldChildShape, newShape, 0, 0);
+ childShapes.add(oldChildShape);
+ }
+ Connection oldChildConnection = findConnection(oldChildObject);
+ if (oldChildConnection != null) {
+ childConnections.add(oldChildConnection);
}
}
- iter = oldObject.eAllContents();
- while (iter.hasNext()) {
- // do the same for connections
- EObject oldChildObject = iter.next();
- // if the old child has a Graphiti Connection, duplicate it.
- Connection oldChildConnection = findConnection(oldChildObject);
- if (oldChildConnection != null) {
- // the old BPMN2 object is a Connection, copy it
- copyConnection(oldChildConnection, newShape, x, y);
- }
+ for (ContainerShape oldChildShape : childShapes) {
+ copyShape(oldChildShape, newShape, 0, 0);
+ }
+
+ for (Connection oldChildConnection : childConnections) {
+ copyConnection(oldChildConnection, newShape, x, y);
}
}
else if (oldObject instanceof Lane) {
@@ -660,7 +710,7 @@
}
}
- // also copy the BPMNShape properties
+ // also copy the BPMNEdge properties
if (oldObject instanceof BaseElement) {
BPMNEdge oldBpmnEdge = DIUtils.findBPMNEdge((BaseElement)oldObject);
if (oldBpmnEdge!=null) {
@@ -683,7 +733,7 @@
public boolean matches(Shape shape) {
if (shape instanceof ContainerShape) {
BaseElement be = getContainerObject((ContainerShape) shape);
- return be instanceof FlowElementsContainer;
+ return be instanceof FlowElementsContainer || be instanceof Participant;
}
return false;
}
@@ -699,9 +749,11 @@
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)
+ if (bo instanceof FlowElementsContainer || bo instanceof Lane || bo instanceof Collaboration)
return (BaseElement) bo;
return null;
}
diff --git a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/label/UpdateLabelFeature.java b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/label/UpdateLabelFeature.java
index 6675631..7c3c5e1 100644
--- a/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/label/UpdateLabelFeature.java
+++ b/plugins/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/features/label/UpdateLabelFeature.java
@@ -231,10 +231,12 @@
BPMNLabel bpmnLabel = null;
if (ownerPE instanceof Connection) {
BPMNEdge bpmnEdge = DIUtils.findBPMNEdge(element);
- bpmnLabel = bpmnEdge.getLabel();
+ if (bpmnEdge!=null)
+ bpmnLabel = bpmnEdge.getLabel();
} else {
BPMNShape bpmnShape = DIUtils.findBPMNShape(element);
- bpmnLabel = bpmnShape.getLabel();
+ if (bpmnShape!=null)
+ bpmnLabel = bpmnShape.getLabel();
}
Bounds bounds = bpmnLabel == null ? null : bpmnLabel.getBounds();
diff --git a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/ConnectionLayerClippingStrategy.java b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/ConnectionLayerClippingStrategy.java
index ae3f910..0700cdd 100644
--- a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/ConnectionLayerClippingStrategy.java
+++ b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/ConnectionLayerClippingStrategy.java
@@ -27,6 +27,7 @@
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
+import org.eclipse.graphiti.datatypes.ILocation;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.pictograms.AnchorContainer;
import org.eclipse.graphiti.mm.pictograms.Connection;
@@ -143,7 +144,8 @@
}
private Rectangle[] getClip(ContainerShape pe) {
+ ILocation loc = Graphiti.getPeService().getLocationRelativeToDiagram(pe);
GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();
- return new Rectangle[] { new Rectangle(ga.getX(), ga.getY(), ga.getWidth(), ga.getHeight()) };
+ return new Rectangle[] { new Rectangle(loc.getX(), loc.getY(), ga.getWidth(), ga.getHeight()) };
}
}