| /******************************************************************************* |
| * 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.util; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.bpel.model.Activity; |
| import org.eclipse.bpel.model.BPELFactory; |
| import org.eclipse.bpel.model.Flow; |
| import org.eclipse.bpel.model.Link; |
| import org.eclipse.bpel.model.Source; |
| import org.eclipse.bpel.model.Target; |
| import org.eclipse.emf.ecore.EObject; |
| |
| |
| |
| /** |
| * Helpers for dealing with Links in a Flow. |
| * |
| * TODO: do all these helpers work OK if the Sources or Targets list is empty?? |
| */ |
| public class FlowLinkUtil { |
| |
| /** |
| * Walks up the parent chain of the source and target activities to find the innermost flow |
| * which contains both. Returns null if source and target have no common flow. |
| */ |
| public static Flow getCommonFlow(Activity source, Activity target) { |
| if (source == null || target == null) return null; |
| Flow[] sourceParents = getParentFlows(source); |
| Flow[] targetParents = getParentFlows(target); |
| if (sourceParents == null || targetParents == null) return null; |
| int sIdx = sourceParents.length - 1; |
| int tIdx = targetParents.length - 1; |
| Flow commonFlow = null; |
| while (sIdx >= 0 && tIdx >= 0) { |
| if (sourceParents[sIdx] == targetParents[tIdx]) { |
| commonFlow = sourceParents[sIdx]; |
| } else { |
| break; |
| } |
| sIdx--; tIdx--; |
| } |
| return commonFlow; |
| } |
| |
| /** |
| * Returns true if the given object is enclosed in a flow, or false otherwise. |
| */ |
| public static boolean hasParentFlow(EObject object) { |
| for (object = object.eContainer(); object != null; object = object.eContainer()) { |
| if (object instanceof Flow) return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Walks up the parent chain of the given object and returns all the parents which are |
| * Flows, from the innermost (i.e. closest ancestor) to outermost (oldest ancestor). |
| * |
| * The returned array will have non-zero length if and only if hasParentFlow(object) is true. |
| */ |
| public static Flow[] getParentFlows(EObject object) { |
| List list = new ArrayList(); |
| getParentFlows(object.eContainer(), list); |
| return (Flow[])list.toArray(new Flow[list.size()]); |
| } |
| |
| protected static void getParentFlows(EObject object, List list) { |
| if (object == null) return; |
| if (object instanceof Process) return; |
| if (object instanceof Flow) list.add(object); |
| getParentFlows(object.eContainer(), list); |
| } |
| |
| /** |
| * Returns a list of links. |
| * Callers should NOT MODIFY this list as it may not be the real list! |
| */ |
| public static List getFlowLinks(Flow flow) { |
| if (flow.getLinks() == null) { |
| return Collections.EMPTY_LIST; |
| } |
| return Collections.unmodifiableList(flow.getLinks().getChildren()); |
| } |
| |
| public static void addFlowLink(Flow flow, Link link) { |
| if (flow.getLinks() == null) { |
| flow.setLinks(BPELFactory.eINSTANCE.createLinks()); |
| } |
| flow.getLinks().getChildren().add(link); |
| } |
| |
| public static void removeFlowLink(Flow flow, Link link) { |
| if (flow.getLinks() != null) { |
| flow.getLinks().getChildren().remove(link); |
| if (flow.getLinks().getChildren().isEmpty()) { |
| flow.setLinks(null); |
| } |
| } |
| } |
| |
| public static void removeActivitySource(Source source) { |
| Activity activity = source.getActivity(); |
| if (activity != null && activity.getSources() != null) { |
| activity.getSources().getChildren().remove(source); |
| if (activity.getSources().getChildren().isEmpty()) { |
| activity.setSources(null); |
| } |
| } |
| } |
| |
| public static void removeActivityTarget(Target target) { |
| Activity activity = target.getActivity(); |
| if (activity != null && activity.getTargets() != null) { |
| activity.getTargets().getChildren().remove(target); |
| if (activity.getTargets().getChildren().isEmpty()) { |
| activity.setTargets(null); |
| } |
| } |
| } |
| |
| /** |
| * Returns the source of a Link, or null if it has none. |
| */ |
| public static Activity getLinkSource(Link link) { |
| if (link.getSources().isEmpty()) return null; |
| return ((link.getSources().get(0))).getActivity(); |
| } |
| |
| /** |
| * Returns the target of a Link, or null if it has none. |
| */ |
| public static Activity getLinkTarget(Link link) { |
| if (link.getTargets().isEmpty()) return null; |
| return ((link.getTargets().get(0))).getActivity(); |
| } |
| |
| /** |
| * Sets the source of a Link. |
| */ |
| public static void setLinkSource(Link link, Activity activity) { |
| if (link.getSources().isEmpty()) { |
| if (activity != null) { |
| // Create new Source. |
| Source source = BPELFactory.eINSTANCE.createSource(); |
| link.getSources().add(source); |
| source.setActivity(activity); |
| } |
| } else { |
| Source source = (link.getSources().get(0)); |
| Activity oldActivity = source.getActivity(); |
| if (activity != null) { |
| // Re-target existing Source. TODO: is this safe? |
| source.setActivity(activity); |
| } else { |
| link.getSources().remove(source); |
| } |
| // In either case, the previous activity to which the |
| // source was attached may now have an empty sources element. |
| // If so, remove it now. |
| if (oldActivity != null) { |
| if (oldActivity.getSources() != null && oldActivity.getSources().getChildren().isEmpty()) { |
| oldActivity.setSources(null); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Sets the target of a Link. |
| */ |
| public static void setLinkTarget(Link link, Activity activity) { |
| if (link.getTargets().isEmpty()) { |
| if (activity != null) { |
| // Create new Target. |
| Target target = BPELFactory.eINSTANCE.createTarget(); |
| link.getTargets().add(target); |
| target.setActivity(activity); |
| } |
| } else { |
| Target target = (link.getTargets().get(0)); |
| Activity oldActivity = target.getActivity(); |
| if (activity != null) { |
| // Re-target existing Target. TODO: is this safe? |
| target.setActivity(activity); |
| } else { |
| // Remove existing Target. |
| link.getTargets().remove(target); |
| } |
| // In either case, the previous activity to which the |
| // target was attached may now have an empty targets element. |
| // If so, remove it now. |
| if (oldActivity != null) { |
| if (oldActivity.getTargets() != null && oldActivity.getTargets().getChildren().isEmpty()) { |
| oldActivity.setTargets(null); |
| } |
| } |
| } |
| } |
| |
| /** |
| * If the from Activity is a source or target in a Link it is |
| * replaced by the to Activity. Nothing happens otherwise. |
| * |
| * TODO: this was only used by some generic fault-handler stuff in ActivityAdapter. |
| * Consider removing this in the future, if we don't need that stuff anymore! |
| */ |
| public static void replaceLinkSourceAndTarget(Activity from, Activity to) { |
| Flow[] flows = getParentFlows(from); |
| if (flows != null && flows.length > 0) { |
| Flow flow = flows[0]; |
| List links = getFlowLinks(flow); |
| for (Iterator iter = links.iterator(); iter.hasNext();) { |
| Link link = (Link) iter.next(); |
| Activity temp = getLinkSource(link); |
| if (temp != null && temp == from) { |
| setLinkSource(link, to); |
| } else { |
| temp = getLinkTarget(link); |
| if (temp != null && temp == from) { |
| setLinkTarget(link, to); |
| } |
| } |
| } |
| } |
| } |
| |
| // /** |
| // * Returns the EditPart which should act as the source for a given Link object. |
| // * (this depends on the collapsed/expanded state..its basically the source Activity |
| // * itself, or its innermost enclosing container, which is actually visible) |
| // */ |
| // public static EditPart getActingSourceEditPart(EditPartViewer viewer, Link link) { |
| // EObject modelObject = getLinkSource(link); |
| // while (modelObject != null) { |
| // EditPart editPart = (EditPart)viewer.getEditPartRegistry().get(modelObject); |
| // if (editPart != null) return editPart; |
| // modelObject = BPELUtil.getIContainerParent(modelObject); |
| // } |
| // return null; |
| // } |
| // |
| // /** |
| // * Returns the EditPart which should act as the target for a given Link object. |
| // * (this depends on the collapsed/expanded state..its basically the target Activity |
| // * itself, or its innermost enclosing container, which is actually visible) |
| // */ |
| // public static EditPart getActingTargetEditPart(EditPartViewer viewer, Link link) { |
| // EObject modelObject = getLinkTarget(link); |
| // while (modelObject != null) { |
| // EditPart editPart = (EditPart)viewer.getEditPartRegistry().get(modelObject); |
| // if (editPart != null) return editPart; |
| // modelObject = BPELUtil.getIContainerParent(modelObject); |
| // } |
| // return null; |
| // } |
| // |
| // /** |
| // * Return all the links for which a collapsed edit part should act as the source, |
| // * even though it really isn't. (Because the *actual* sources are contained in |
| // * the edit part). |
| // */ |
| // public static List getAllContainedSourceLinks(EObject model) { |
| // List result = new ArrayList(); |
| // for (TreeIterator it = model.eAllContents(); it.hasNext(); ) { |
| // Object object = it.next(); |
| // // Activity *contains* the Sources which *contains* the Source |
| // if (object instanceof Source) { |
| // Link link = ((Source)object).getLink(); |
| // if (link != null) result.add(link); |
| // } |
| // } |
| // return result; |
| // } |
| // |
| // /** |
| // * Return all the links for which a collapsed edit part should act as the source, |
| // * even though it really isn't. (Because the *actual* sources are contained in |
| // * the edit part). |
| // */ |
| // public static List getAllContainedTargetLinks(EObject model) { |
| // List result = new ArrayList(); |
| // for (TreeIterator it = model.eAllContents(); it.hasNext(); ) { |
| // Object object = it.next(); |
| // // Activity *contains* the Sources which *contains* the Source |
| // if (object instanceof Source) { |
| // Link link = ((Source)object).getLink(); |
| // if (link != null) result.add(link); |
| // } |
| // } |
| // return result; |
| // } |
| |
| } |