blob: b033f2379cdb63809762fbe57ee198f1e50e0097 [file] [log] [blame]
/*******************************************************************************
* 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;
// }
}