package org.activiti.designer.features;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.activiti.bpmn.model.BaseElement;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Lane;
import org.activiti.bpmn.model.Pool;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.designer.util.editor.Bpmn2MemoryModel;
import org.activiti.designer.util.editor.ModelHandler;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.IRemoveFeature;
import org.eclipse.graphiti.features.context.IDeleteContext;
import org.eclipse.graphiti.features.context.IRemoveContext;
import org.eclipse.graphiti.features.context.impl.RemoveContext;
import org.eclipse.graphiti.features.context.impl.ResizeShapeContext;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.ui.features.DefaultDeleteFeature;
public class DeleteLaneFeature extends DefaultDeleteFeature {
private int laneHeight;
private int laneY;
public DeleteLaneFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canDelete(IDeleteContext context) {
PictogramElement pictogramElement = context.getPictogramElement();
Object bo = getFeatureProvider().getBusinessObjectForPictogramElement(pictogramElement);
if (bo instanceof Lane) {
return true;
} else {
return false;
}
}
@Override
public void preDelete(IDeleteContext context) {
Shape laneShape = (Shape) context.getPictogramElement();
laneHeight = laneShape.getGraphicsAlgorithm().getHeight();
laneY = laneShape.getGraphicsAlgorithm().getY();
}
protected void deleteBusinessObject(Object bo) {
if (bo instanceof Lane) {
Bpmn2MemoryModel model = ModelHandler.getModel(EcoreUtil.getURI(getDiagram()));
Lane lane = (Lane) bo;
Pool parentPool = null;
for (Pool pool : model.getBpmnModel().getPools()) {
if(pool.getProcessRef().equalsIgnoreCase(lane.getParentProcess().getId())) {
parentPool = pool;
break;
}
}
Process laneProcess = model.getBpmnModel().getProcess(parentPool.getId());
if (parentPool == null || laneProcess == null) return;
if(laneProcess.getLanes().size() == 1) {
Process process = model.getBpmnModel().getProcess(parentPool.getId());
model.getBpmnModel().getProcesses().remove(process);
model.getBpmnModel().getPools().remove(parentPool);
PictogramElement poolElement = getFeatureProvider().getPictogramElementForBusinessObject(parentPool);
IRemoveContext poolRc = new RemoveContext(poolElement);
IRemoveFeature poolRemoveFeature = getFeatureProvider().getRemoveFeature(poolRc);
if (poolRemoveFeature != null) {
poolRemoveFeature.remove(poolRc);
}
} else {
Shape poolShape = (Shape) getFeatureProvider().getPictogramElementForBusinessObject(parentPool);
ResizeShapeContext resizeContext = new ResizeShapeContext(poolShape);
resizeContext.setSize(poolShape.getGraphicsAlgorithm().getWidth(), poolShape.getGraphicsAlgorithm().getHeight() - laneHeight);
resizeContext.setLocation(poolShape.getGraphicsAlgorithm().getX(), poolShape.getGraphicsAlgorithm().getY());
resizeContext.setDirection(ResizeShapeContext.DIRECTION_NORTH);
resizeContext.putProperty("org.activiti.designer.lane.create", true);
getFeatureProvider().getResizeShapeFeature(resizeContext).execute(resizeContext);
}
for (Lane otherLane : lane.getParentProcess().getLanes()) {
if(otherLane.equals(lane)) continue;
Shape otherLaneShape = (Shape) getFeatureProvider().getPictogramElementForBusinessObject(otherLane);
if(otherLaneShape.getGraphicsAlgorithm().getY() > laneY) {
otherLaneShape.getGraphicsAlgorithm().setY(otherLaneShape.getGraphicsAlgorithm().getY() - laneHeight);
}
}
List<FlowElement> toDeleteElements = new ArrayList<FlowElement>();
for (String flowRef : lane.getFlowReferences()) {
for (FlowElement flowElement : lane.getParentProcess().getFlowElements()) {
if(flowRef.equalsIgnoreCase(flowElement.getId())) {
toDeleteElements.add(flowElement);
}
}
}
for (FlowElement subFlowElement : toDeleteElements) {
if(subFlowElement instanceof FlowNode) {
deleteSequenceFlows((FlowNode) subFlowElement);
}
removeElement(subFlowElement);
}
lane.getParentProcess().getLanes().remove(lane);
}
}
private void removeElement(BaseElement element) {
List<Process> processes = ModelHandler.getModel(EcoreUtil.getURI(getDiagram())).getBpmnModel().getProcesses();
for (Process process : processes) {
process.removeFlowElement(element.getId());
removeElementInProcess(element, process);
}
}
private void removeElementInProcess(BaseElement element, BaseElement parentElement) {
Collection<FlowElement> elementList = null;
if (parentElement instanceof Process) {
elementList = ((Process) parentElement).getFlowElements();
} else if (parentElement instanceof SubProcess) {
elementList = ((SubProcess) parentElement).getFlowElements();
}
for (FlowElement flowElement : elementList) {
if(flowElement instanceof SubProcess) {
SubProcess subProcess = (SubProcess) flowElement;
subProcess.removeFlowElement(element.getId());
removeElementInProcess(element, subProcess);
}
}
}
private void deleteSequenceFlows(FlowNode flowNode) {
List<SequenceFlow> toDeleteSequenceFlows = new ArrayList<SequenceFlow>();
for (SequenceFlow incomingSequenceFlow : flowNode.getIncomingFlows()) {
toDeleteSequenceFlows.add(incomingSequenceFlow);
}
for (SequenceFlow outgoingSequenceFlow : flowNode.getOutgoingFlows()) {
toDeleteSequenceFlows.add(outgoingSequenceFlow);
}
for (SequenceFlow deleteObject : toDeleteSequenceFlows) {
IRemoveContext rc = new RemoveContext(getFeatureProvider().getPictogramElementForBusinessObject(deleteObject));
IFeatureProvider featureProvider = getFeatureProvider();
IRemoveFeature removeFeature = featureProvider.getRemoveFeature(rc);
if (removeFeature != null) {
removeFeature.remove(rc);
}
Bpmn2MemoryModel model = ModelHandler.getModel(EcoreUtil.getURI(getDiagram()));
FlowNode sourceNode = (FlowNode) model.getFlowElement(deleteObject.getSourceRef());
FlowNode targetNode = (FlowNode) model.getFlowElement(deleteObject.getTargetRef());
if (sourceNode != null) {
sourceNode.getOutgoingFlows().remove(deleteObject);
}
if (targetNode != null) {
targetNode.getIncomingFlows().remove(deleteObject);
}
removeElement(deleteObject);
}
}
}