| /******************************************************************************* |
| * Copyright (c) 2005, 2012 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.bpel.ui.editparts.policies; |
| |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.bpel.model.Activity; |
| import org.eclipse.bpel.model.BPELFactory; |
| import org.eclipse.bpel.model.BPELPackage; |
| import org.eclipse.bpel.model.CompensateScope; |
| import org.eclipse.bpel.model.Flow; |
| import org.eclipse.bpel.model.Link; |
| import org.eclipse.bpel.model.PartnerLink; |
| import org.eclipse.bpel.model.Process; |
| import org.eclipse.bpel.model.Source; |
| import org.eclipse.bpel.model.Target; |
| import org.eclipse.bpel.model.Variable; |
| import org.eclipse.bpel.model.util.BPELUtils; |
| import org.eclipse.bpel.ui.BPELLinkCreationFactory; |
| import org.eclipse.bpel.ui.BPELUIPlugin; |
| import org.eclipse.bpel.ui.IBPELUIConstants; |
| import org.eclipse.bpel.ui.Messages; |
| import org.eclipse.bpel.ui.commands.AddLinkCommand; |
| import org.eclipse.bpel.ui.commands.CompoundCommand; |
| import org.eclipse.bpel.ui.commands.ReplaceInContainerCommand; |
| import org.eclipse.bpel.ui.commands.SetCompensateCommand; |
| import org.eclipse.bpel.ui.commands.SetNameCommand; |
| import org.eclipse.bpel.ui.commands.SetPartnerLinkCommand; |
| import org.eclipse.bpel.ui.commands.SetVariableCommand; |
| import org.eclipse.bpel.ui.editparts.ActivityEditPart; |
| import org.eclipse.bpel.ui.editparts.BPELEditPart; |
| import org.eclipse.bpel.ui.editparts.PartnerLinkEditPart; |
| import org.eclipse.bpel.ui.editparts.VariableEditPart; |
| import org.eclipse.bpel.ui.figures.CenteredConnectionAnchor; |
| import org.eclipse.bpel.ui.util.BPELUtil; |
| import org.eclipse.bpel.ui.util.FlowLinkUtil; |
| import org.eclipse.bpel.ui.util.ModelHelper; |
| import org.eclipse.draw2d.Connection; |
| import org.eclipse.draw2d.ConnectionAnchor; |
| import org.eclipse.draw2d.ManhattanConnectionRouter; |
| import org.eclipse.draw2d.PolygonDecoration; |
| import org.eclipse.draw2d.PolylineConnection; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.LayerConstants; |
| import org.eclipse.gef.NodeEditPart; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gef.commands.Command; |
| import org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy; |
| import org.eclipse.gef.requests.CreateConnectionRequest; |
| import org.eclipse.gef.requests.CreateRequest; |
| import org.eclipse.gef.requests.ReconnectRequest; |
| |
| |
| public class BPELGraphicalEditPolicy extends GraphicalNodeEditPolicy { |
| |
| final static private int FLOWLINK = 3, COMPENSATELINK = 4; |
| |
| private int getLinkMode(CreateConnectionRequest req) { |
| if (req.getStartCommand().getClass().equals(SetCompensateCommand.class)) |
| return COMPENSATELINK; |
| return FLOWLINK; |
| } |
| |
| protected Command createSetNameCommand(Link link, Process process) { |
| if (link == null) return null; |
| return new SetNameCommand(link, BPELUtil.getUniqueModelName( |
| process, Messages.BPELGraphicalEditPolicy_link1_1, Collections.singletonList(link))); |
| } |
| |
| @Override |
| protected Command getConnectionCreateCommand(CreateConnectionRequest request) { |
| if (getHost() == null) |
| return null; |
| if (request.getNewObjectType().equals(BPELPackage.eINSTANCE.getLink())) { |
| Activity activity = getActivity(); |
| if (activity == null) |
| return null; |
| |
| if (!FlowLinkUtil.hasParentFlow(activity)) { |
| return null; |
| } |
| Link link = BPELFactory.eINSTANCE.createLink(); |
| Source source = BPELFactory.eINSTANCE.createSource(); |
| Target target = BPELFactory.eINSTANCE.createTarget(); |
| link.getSources().add(source); |
| link.getTargets().add(target); |
| Process process = BPELUtils.getProcess(activity); |
| AddLinkCommand command = new AddLinkCommand(createSetNameCommand(link, process), process); |
| command.setLink(link); |
| command.setSource(activity); |
| request.setStartCommand(command); |
| return command; |
| } |
| else if (request.getNewObjectType().equals(BPELLinkCreationFactory.PartnerTempLink.class)) { |
| Activity activity = getActivity(); |
| if (activity == null) |
| return null; |
| SetPartnerLinkCommand command = new SetPartnerLinkCommand(activity, null); |
| request.setStartCommand(command); |
| return command; |
| } |
| else if (request.getNewObjectType().equals(BPELLinkCreationFactory.IncomingVarTempLink.class)) { |
| Activity activity = getActivity(); |
| if (activity == null) |
| return null; |
| SetVariableCommand command = new SetVariableCommand(activity, null, ModelHelper.INCOMING); |
| request.setStartCommand(command); |
| return command; |
| } |
| else if (request.getNewObjectType().equals(BPELLinkCreationFactory.CompensateTempLink.class)) { |
| Activity activity = getActivity(); |
| if (activity == null) |
| return null; |
| SetCompensateCommand command = new SetCompensateCommand((CompensateScope)activity, null); |
| request.setStartCommand(command); |
| return command; |
| } |
| else if (request.getNewObjectType().equals(BPELLinkCreationFactory.OutgoingVarTempLink.class)) { |
| Activity activity = getActivity(); |
| if (activity == null) |
| return null; |
| SetVariableCommand command = new SetVariableCommand(activity, null, ModelHelper.OUTGOING); |
| request.setStartCommand(command); |
| return command; |
| } |
| else { |
| // invalid request parameter |
| // should we throw an error? |
| return null; |
| } |
| } |
| |
| /** |
| * Create a polyline connection from sourceAnchor to targetAnchor. |
| * Add arrows as specified by the arguments. |
| * Add the connection to the connection layer and return it. |
| */ |
| private PolylineConnection createConnection(ConnectionAnchor sourceAnchor, ConnectionAnchor targetAnchor, boolean sourceArrow, boolean targetArrow) { |
| PolylineConnection connection = new PolylineConnection(); |
| if (sourceAnchor != null) |
| connection.setSourceAnchor(sourceAnchor); |
| if (targetAnchor != null) |
| connection.setTargetAnchor(targetAnchor); |
| connection.setForegroundColor(BPELUIPlugin.INSTANCE.getColorRegistry().get(IBPELUIConstants.COLOR_BLUE)); |
| connection.setBackgroundColor(BPELUIPlugin.INSTANCE.getColorRegistry().get(IBPELUIConstants.COLOR_BLUE)); |
| connection.setConnectionRouter(new ManhattanConnectionRouter()); |
| PolygonDecoration arrow = new PolygonDecoration(); |
| arrow.setTemplate(PolygonDecoration.TRIANGLE_TIP); |
| arrow.setScale(5,2.5); |
| arrow.setBackgroundColor(BPELUIPlugin.INSTANCE.getColorRegistry().get(IBPELUIConstants.COLOR_BLUE)); |
| if (targetArrow) { |
| connection.setTargetDecoration(arrow); |
| } |
| if (sourceArrow) { |
| connection.setSourceDecoration(arrow); |
| } |
| getLayer(LayerConstants.CONNECTION_LAYER).add(connection); |
| return connection; |
| } |
| |
| @Override |
| protected Connection createDummyConnection(Request req) { |
| if (getLinkMode((CreateConnectionRequest)req) == FLOWLINK) |
| return super.createDummyConnection(req); |
| return createConnection(null, null, false, true); |
| } |
| |
| @Override |
| protected Command getConnectionCompleteCommand(CreateConnectionRequest request) { |
| Command startCommand = request.getStartCommand(); |
| if (getLinkMode(request) == FLOWLINK) { |
| AddLinkCommand command = (AddLinkCommand)startCommand; |
| Activity activity = getActivity(); |
| if (activity == null || !FlowLinkUtil.hasParentFlow(activity)) { |
| return null; |
| } |
| command.setTarget(activity); |
| if (!command.canExecute()) return null; |
| ConnectionAnchor ctor = getActivityEditPart().getTargetConnectionAnchor(request); |
| if (ctor == null) { |
| return null; |
| } |
| return command; |
| } |
| else if (getLinkMode(request) == COMPENSATELINK) { |
| SetCompensateCommand command = (SetCompensateCommand)startCommand; |
| Activity compensate = getActivity(); |
| |
| // true if activity selected is in list of valid activities that |
| // compensate can point to |
| boolean b = BPELUtil.getCompensableActivities(command.getTarget()).contains(compensate); |
| |
| if (compensate == null || !b) { |
| return null; |
| } |
| command.setNewValue(compensate); |
| if (!command.canExecute()) |
| return null; |
| ConnectionAnchor ctor = ((BPELEditPart)request.getTargetEditPart()).getConnectionAnchor(CenteredConnectionAnchor.LEFT); |
| if (ctor == null) { |
| return null; |
| } |
| return command; |
| } |
| return null; |
| } |
| |
| @Override |
| protected Command getReconnectTargetCommand(ReconnectRequest request) { |
| Activity activity = getActivity(); |
| Link link = (Link)request.getConnectionEditPart().getModel(); |
| Process process = BPELUtils.getProcess(activity); |
| AddLinkCommand cmd = new AddLinkCommand(createSetNameCommand(link, process), process); |
| cmd.setLink(link); |
| |
| // it's necessary to set also the source so the move command can be excecuted. Otherwise the flow cannot be identified and |
| // the connection of the link is not moved. |
| // As the link has only one source take the first item of the sources list. |
| if (link.getSources().size() > 0) |
| cmd.setSource((link.getSources().get(0)).getActivity()); |
| cmd.setTarget(activity); |
| return cmd; |
| } |
| |
| @Override |
| protected Command getReconnectSourceCommand(ReconnectRequest request) { |
| Activity activity = getActivity(); |
| Link link = (Link)request.getConnectionEditPart().getModel(); |
| Process process = BPELUtils.getProcess(activity); |
| AddLinkCommand cmd = new AddLinkCommand(createSetNameCommand(link, process), process); |
| cmd.setLink(link); |
| |
| // it's necessary to set also the target so the move command can be excecuted. Otherwise the flow cannot be identified and |
| // the connection of the link is not moved. |
| // As the link has only one target take the first item of the sources list. |
| if (link.getTargets().size() > 0) |
| cmd.setTarget((link.getTargets().get(0)).getActivity()); |
| cmd.setSource(activity); |
| return cmd; |
| } |
| |
| protected ActivityEditPart getActivityEditPart() { |
| if (getHost() instanceof ActivityEditPart) { |
| return (ActivityEditPart)getHost(); |
| } |
| return null; |
| } |
| |
| protected Activity getActivity() { |
| EditPart ep = getActivityEditPart(); |
| if (ep == null) |
| return null; |
| return (Activity)ep.getModel(); |
| } |
| |
| protected PartnerLinkEditPart getPartnerEditPart() { |
| EditPart ep = getHost(); |
| if (ep instanceof PartnerLinkEditPart) |
| return (PartnerLinkEditPart)getHost(); |
| return null; |
| } |
| |
| protected PartnerLink getPartnerLink() { |
| if (!(getHost() instanceof PartnerLinkEditPart)) |
| return null; |
| Object model = getHost().getModel(); |
| return (PartnerLink)model; |
| } |
| |
| protected Variable getVariable() { |
| if (!(getHost() instanceof VariableEditPart)) |
| return null; |
| Object model = getHost().getModel(); |
| return (Variable)model; |
| } |
| |
| @Override |
| protected ConnectionAnchor getSourceConnectionAnchor(CreateConnectionRequest request) { |
| EditPart source = request.getSourceEditPart(); |
| if (source instanceof NodeEditPart) { |
| if (getLinkMode(request) == FLOWLINK) |
| return ((NodeEditPart) source).getSourceConnectionAnchor(request); |
| return ((BPELEditPart) source).getConnectionAnchor(CenteredConnectionAnchor.LEFT); |
| } |
| return null; |
| } |
| |
| @Override |
| protected ConnectionAnchor getTargetConnectionAnchor(CreateConnectionRequest request) { |
| EditPart target = request.getTargetEditPart(); |
| if (target instanceof NodeEditPart) { |
| // make sure object is INSIDE a flow |
| |
| if (!FlowLinkUtil.hasParentFlow((EObject)target.getModel())) |
| return null; |
| |
| if (getLinkMode(request) == FLOWLINK) { |
| // does it make sense to allow two links with the same source and dest? |
| // I assume not, so we'll prevent it. |
| |
| // iterate through all the current links |
| EditPart source = request.getSourceEditPart(); |
| Flow flows[] = FlowLinkUtil.getParentFlows((EObject)source.getModel()); |
| for (int i = 0; i< flows.length; i++) { |
| List links = FlowLinkUtil.getFlowLinks(flows[i]); |
| for (int j = 0; j < links.size(); j++) { |
| Link link = (Link)links.get(j); |
| if (FlowLinkUtil.getLinkSource(link) == source.getModel() && |
| FlowLinkUtil.getLinkTarget(link) == target.getModel()) |
| return null; |
| } |
| } |
| return ((NodeEditPart) target).getTargetConnectionAnchor(request); |
| } |
| } |
| |
| // (VZ) FIXME: we cannot cast target to BPELEditPart instance. Debug it... |
| else if (target instanceof PartnerLinkEditPart) |
| return ((BPELEditPart)target).getConnectionAnchor(CenteredConnectionAnchor.LEFT); |
| else if (target instanceof VariableEditPart) |
| return ((BPELEditPart)target).getConnectionAnchor(CenteredConnectionAnchor.RIGHT); |
| return null; |
| } |
| |
| @Override |
| public Command getCommand(Request request) { |
| if ("changeType".equals(request.getType())) //$NON-NLS-1$ |
| return getReplaceInContainerCommand((CreateRequest)request); |
| return super.getCommand(request); |
| } |
| |
| protected Command getReplaceInContainerCommand(CreateRequest request) { |
| Object target = getHost().getParent().getModel(); |
| Object oldElement = getHost().getModel(); |
| Object newElement = request.getNewObject(); |
| |
| //Only change type for Activity |
| // TODO: remove this limitation in the future ? |
| if (!(oldElement instanceof Activity)) return null; |
| |
| CompoundCommand command = new CompoundCommand(); |
| command.add(new ReplaceInContainerCommand(target, oldElement, newElement)); |
| |
| //Update the display name as stored in the extension |
| // TODO |
| |
| return command; |
| } |
| } |
| |