/*******************************************************************************
* Copyright (c) 2011, 2012 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
*
* @author Innar Made
******************************************************************************/
package org.eclipse.bpmn2.modeler.ui.features.participant;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.bpmn2.Collaboration;
import org.eclipse.bpmn2.Definitions;
import org.eclipse.bpmn2.FlowElementsContainer;
import org.eclipse.bpmn2.Participant;
import org.eclipse.bpmn2.di.BPMNDiagram;
import org.eclipse.bpmn2.modeler.core.di.DIUtils;
import org.eclipse.bpmn2.modeler.core.features.choreography.ChoreographyUtil;
import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil;
import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;
import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
import org.eclipse.bpmn2.modeler.ui.features.AbstractDefaultDeleteFeature;
import org.eclipse.dd.di.DiagramElement;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.graphiti.features.IDeleteFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IDeleteContext;
import org.eclipse.graphiti.features.context.impl.DeleteContext;
import org.eclipse.graphiti.mm.pictograms.Connection;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
public class DeleteParticipantFeature extends AbstractDefaultDeleteFeature {
boolean isReference = false;
public DeleteParticipantFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canDelete(IDeleteContext context) {
// Participant bands in a ChoreographyTask only be "deleted" (from the model)
// if there are no other references to the participant; but they can be "removed"
// (from the ChoreographyTask's participantRef list) at any time.
// @see RemoveChoreographyParticipantFeature
PictogramElement pe = context.getPictogramElement();
if (ChoreographyUtil.isChoreographyParticipantBand(pe)) {
int referenceCount = 0;
Participant participant = BusinessObjectUtil.getFirstElementOfType(pe, Participant.class);
Definitions definitions = ModelUtil.getDefinitions(participant);
TreeIterator<EObject> iter = definitions.eAllContents();
while (iter.hasNext()) {
EObject o = iter.next();
for (EReference reference : o.eClass().getEAllReferences()) {
if (!reference.isContainment() && !(o instanceof DiagramElement)) {
if (reference.isMany()) {
List list = (List)o.eGet(reference);
for (Object referencedObject : list) {
if (referencedObject==participant)
++referenceCount;
}
}
else {
Object referencedObject = o.eGet(reference);
if (referencedObject == participant)
++referenceCount;
}
}
}
}
return referenceCount <= 1;
}
return true;
}
@Override
public void delete(IDeleteContext context) {
// Delete the pool's process and the BPMNDiagram page (if any).
Collaboration collaboration = null;
PictogramElement pe = context.getPictogramElement();
if (pe instanceof ContainerShape) {
ContainerShape poolShape = (ContainerShape) pe;
Object bo = getBusinessObjectForPictogramElement(pe);
if (bo instanceof Participant) {
Participant participant = (Participant) bo;
if (FeatureSupport.isParticipantReference(getDiagram(), participant)) {
isReference = true;;
}
if (!isReference) {
Definitions definitions = ModelUtil.getDefinitions(participant);
List<Collaboration> collaborations = ModelUtil.getAllRootElements(definitions, Collaboration.class);
for (Collaboration c : collaborations) {
if (c.getParticipants().contains(participant)) {
collaboration = c;
break;
}
}
// also delete any contained Lanes and their children
List<PictogramElement> children = new ArrayList<PictogramElement>();
FeatureSupport.collectChildren(poolShape, children, true);
for (PictogramElement child : children) {
if (child instanceof Connection) {
// don't bother with Connections, these will
// be deleted by their source/target shapes
continue;
}
IDeleteContext dc = new DeleteContext(child);
IDeleteFeature df = getFeatureProvider().getDeleteFeature(dc);
if (df.canDelete(dc)) {
df.delete(dc);
}
}
bo = participant.getProcessRef();
if (bo instanceof FlowElementsContainer) {
BPMNDiagram bpmnDiagram = DIUtils.findBPMNDiagram((FlowElementsContainer)bo);
if (bpmnDiagram != null) {
DIUtils.deleteDiagram(getDiagramBehavior(), bpmnDiagram);
}
EcoreUtil.delete((FlowElementsContainer)bo, true);
}
}
}
}
super.delete(context);
if (collaboration!=null && collaboration.getParticipants().size()==1) {
Participant lastParticipant = collaboration.getParticipants().get(0);
if (lastParticipant.getProcessRef()!=null && DIUtils.findBPMNShape(lastParticipant)==null) {
// We can delete the final Participant and Collaboration
// as long as the Participant has a Process and does
// not have a Pool shape. The Participant's Process
// will become the Default Process - the entire diagram
BPMNDiagram bpmnDiagram = DIUtils.findBPMNDiagram(collaboration);
EcoreUtil.delete(lastParticipant);
EcoreUtil.delete(collaboration);
if (bpmnDiagram!=null) {
bpmnDiagram.getPlane().setBpmnElement(lastParticipant.getProcessRef());
}
}
}
}
@Override
protected void deleteBusinessObjects(Object[] businessObjects) {
if (businessObjects != null) {
for (Object bo : businessObjects) {
if (bo instanceof Participant) {
if (isReference)
continue;
}
deleteBusinessObject(bo);
}
}
}
}