/******************************************************************************* * 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 Ivar Meikas ******************************************************************************/ package org.eclipse.bpmn2.modeler.core.features.containers.lane; import org.eclipse.bpmn2.Collaboration; import org.eclipse.bpmn2.FlowNode; import org.eclipse.bpmn2.Lane; import org.eclipse.bpmn2.LaneSet; import org.eclipse.bpmn2.Participant; import org.eclipse.bpmn2.Process; import org.eclipse.bpmn2.di.BPMNDiagram; import org.eclipse.bpmn2.modeler.core.features.containers.MoveContainerFeature; import org.eclipse.bpmn2.modeler.core.model.ModelHandler; import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil; import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport; import org.eclipse.emf.ecore.EObject; import org.eclipse.graphiti.features.IFeatureProvider; import org.eclipse.graphiti.features.context.IMoveShapeContext; import org.eclipse.graphiti.features.context.ITargetContext; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.PictogramElement; /** * Handles the moving of Lanes from one container to another. The source and * target containers may be Pools, other Lanes or the Diagram. * * TODO: allow reordering of Lanes within their containers. For example, current * behavior when a Lane is dragged from a Diagram and dropped into another Lane * which already contains child Lanes, the dropped Lane is always added to the * bottom or left of existing child Lanes. It would be useful to allow the user * to select the location of the dropped Lane relative to existing child Lanes, * by looking at the mouse cursor position. */ public class MoveLaneFeature extends MoveContainerFeature { private MoveLaneFeature moveStrategy; protected ModelHandler modelHandler; public MoveLaneFeature(IFeatureProvider fp) { super(fp); modelHandler = ModelHandler.getInstance(getDiagram()); } @Override public boolean canMoveShape(IMoveShapeContext context) { if (context.getSourceContainer() == null) { return false; } moveStrategy = getStrategy(context); if (moveStrategy == null) { return super.canMoveShape(context); } return moveStrategy.canMoveShape(context); } @Override protected void internalMove(IMoveShapeContext context) { super.internalMove(context); if (moveStrategy != null) { moveStrategy.internalMove(context); } } private MoveLaneFeature getStrategy(IMoveShapeContext context) { if (context.getSourceContainer().equals(getDiagram())) { // from diagram if (FeatureSupport.isTargetLane(context)) { // to lane return new MoveFromDiagramToLaneFeature(getFeatureProvider()); } else if (FeatureSupport.isTargetParticipant(context)) { // to participant return new MoveFromDiagramToParticipantFeature(getFeatureProvider()); } } else if (FeatureSupport.isLane(context.getSourceContainer())) { // from lane if (context.getTargetContainer().equals(getDiagram())) { // to diagram return new MoveFromLaneToDiagramFeature(getFeatureProvider()); } else if (FeatureSupport.isTargetLane(context)) { // to another lane return new MoveFromLaneToLaneFeature(getFeatureProvider()); } else if (FeatureSupport.isTargetParticipant(context)) { // to participant return new MoveFromLaneToParticipantFeature(getFeatureProvider()); } } else if (FeatureSupport.isParticipant(context.getSourceContainer())) { // from participant if (context.getTargetContainer().equals(getDiagram())) { // to diagram return new MoveFromParticipantToDiagramFeature(getFeatureProvider()); } else if (FeatureSupport.isTargetLane(context)) { // to another lane return new MoveFromParticipantToLaneFeature(getFeatureProvider()); } else if (FeatureSupport.isTargetParticipant(context)) { // to another participant return new MoveFromParticipantToParticipantFeature(getFeatureProvider()); } } return null; } protected Lane getMovedLane(IMoveShapeContext context) { return (Lane) getBusinessObjectForPictogramElement(context.getShape()); } protected Process getProcess(Object object) { Process process = null; if (object instanceof PictogramElement) { // this could be a Diagram or ContainerShape object = BusinessObjectUtil.getBusinessObjectForPictogramElement((PictogramElement)object); } if (object instanceof BPMNDiagram) { // the BPMNDiagram could be a Process or Collaboration/Choreography object = ((BPMNDiagram)object).getPlane().getBpmnElement(); } if (object instanceof Collaboration) { // the Collaboration contain one or more Participants Participant participant = null; Collaboration collaboration = (Collaboration) object; for (Participant p : collaboration.getParticipants()) { if (p.getProcessRef()!=null) { process = p.getProcessRef(); break; } else if (participant==null) participant = p; } if (process==null) { // create a new Process in the Collaboration's first Participant object = participant; } } if (object instanceof Participant) { Participant participant = (Participant) object; process = participant.getProcessRef(); if (process == null) { // create a new Process process = modelHandler.createObject(Process.class); modelHandler.getDefinitions().getRootElements().add(process); process.setName(participant.getName() + Messages.MoveLaneFeature_Process_Label); if (participant.eContainer() instanceof Collaboration) { process.setDefinitionalCollaborationRef((Collaboration)participant.eContainer()); } participant.setProcessRef(process); } } if (object instanceof Process) { process =(Process) object; } if (process==null && object instanceof EObject) { EObject o = (EObject) object; while (o.eContainer()!=null) { if (o instanceof Process) { process = (Process) o; break; } o = o.eContainer(); } } return process; } protected Lane getTargetLane(ITargetContext context) { ContainerShape targetContainer = context.getTargetContainer(); return (Lane) getBusinessObjectForPictogramElement(targetContainer); } protected Lane getSourceLane(IMoveShapeContext context) { ContainerShape sourceContainer = context.getSourceContainer(); return (Lane) getBusinessObjectForPictogramElement(sourceContainer); } protected LaneSet createLaneSet() { return modelHandler.createObject(LaneSet.class); } protected void moveLane(Lane movedLane, Process sourceProcess, Process targetProcess) { if (sourceProcess!=targetProcess) { for (FlowNode node : movedLane.getFlowNodeRefs()) { modelHandler.moveFlowNode(node, sourceProcess, targetProcess); } if (movedLane.getChildLaneSet() != null && !movedLane.getChildLaneSet().getLanes().isEmpty()) { for (Lane lane : movedLane.getChildLaneSet().getLanes()) { moveLane(lane, sourceProcess, targetProcess); } } } } }