blob: e22fca185928dcd4fd93f8062547c2fb3b06f68c [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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 implementation
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.diagram.core.bridge;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.epf.diagram.model.Diagram;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.util.MethodElementPropertyHelper;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodElementProperty;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.uml2.uml.ActivityEdge;
import org.eclipse.uml2.uml.ActivityNode;
import org.eclipse.uml2.uml.ControlNode;
/**
* @author Phong Nguyen Le
*
* @since 1.2
*/
public class WorkBreakdownElementNodeAdapter extends NodeAdapter {
private class WorkBreakdownElementAdapter extends MethodElementAdapter {
protected Collection handleNotification(Notification msg) {
WorkOrder obj;
switch (msg.getFeatureID(WorkBreakdownElement.class)) {
case UmaPackage.WORK_BREAKDOWN_ELEMENT__LINK_TO_PREDECESSOR:
switch (msg.getEventType()) {
case Notification.ADD:
obj = (WorkOrder) msg.getNewValue();
if(isValid(obj)) {
addIncomingConnection(obj.getPred());
}
break;
case Notification.REMOVE:
obj = (WorkOrder) msg.getOldValue();
removeIncomingConnection(obj.getPred());
break;
case Notification.ADD_MANY:
Collection<?> collection = (Collection<?>) msg.getNewValue();
for (Iterator<?> iter = collection.iterator(); iter.hasNext();) {
obj = (WorkOrder) iter.next();
if(isValid(obj)) {
addIncomingConnection(obj.getPred());
}
}
break;
case Notification.REMOVE_MANY:
collection = (Collection) msg.getOldValue();
for (Iterator iter = collection.iterator(); iter.hasNext();) {
obj = (WorkOrder) iter.next();
removeIncomingConnection(obj.getPred());
}
break;
}
break;
case UmaPackage.WORK_BREAKDOWN_ELEMENT__SUPPRESSED:
switch (msg.getEventType()) {
case Notification.SET:
// Boolean b = (Boolean)msg.getNewValue();
// handleSuppressed(b.booleanValue());
break;
}
break;
default:
return super.handleNotification(msg);
}
return Collections.EMPTY_LIST;
}
}
/**
* @param e
*/
public WorkBreakdownElementNodeAdapter(MethodElement e) {
super(e);
}
/**
* Checks if the specified work order could be valid for the diagram to create
* new connection.
*
* @param wo
* @return
*/
private boolean isValid(WorkOrder wo) {
MethodElementProperty prop = MethodElementPropertyHelper.getProperty(wo, MethodElementPropertyHelper.WORK_ORDER__PREDECESSOR_IS_SIBLING);
if(prop != null) {
return true;
}
ActivityNode node = getNode();
org.eclipse.uml2.uml.Activity diagram = getDiagram();
ActivityDiagramAdapter diagramAdapter = (ActivityDiagramAdapter) BridgeHelper.getDiagramAdapter(diagram);
List<WorkBreakdownElement> localPredecessors = diagramAdapter.getLocalPredecessors(node);
return localPredecessors.contains(wo.getPred());
}
public void handleSuppressed(boolean b) {
if(b){
List incomings = getNode().getIncomings();
for (int i =0; i<incomings.size(); i++) {
Object obj = incomings.get(i);
ActivityEdge link = null;
if(obj != null ){
link = (ActivityEdge)obj;
}
if(link != null && link.getSource() != null){
NodeAdapter sourceNodeAdapter = BridgeHelper.getNodeAdapter(link.getSource());
boolean oldNotify1 = sourceNodeAdapter != null ? sourceNodeAdapter.notificationEnabled : false;
try {
if(sourceNodeAdapter != null) sourceNodeAdapter.notificationEnabled = false;
link.setTarget(null);
getNode().getIncomings().remove(link);
} finally {
if(sourceNodeAdapter != null) sourceNodeAdapter.notificationEnabled = oldNotify1;
}
}
}
List outGoings = getNode().getOutgoings();
for (int i =0; i<outGoings.size(); i++) {
Object obj = outGoings.get(i);
ActivityEdge link = null;
if(obj != null ){
link = (ActivityEdge)obj;
}
if(link != null && link.getTarget() != null){
NodeAdapter nodeAdapter = BridgeHelper.getNodeAdapter(link.getTarget());
boolean oldNotify1 = nodeAdapter != null ? nodeAdapter.notificationEnabled : false;
try {
if(nodeAdapter != null) nodeAdapter.notificationEnabled = false;
link.setSource(null);
getNode().getIncomings().remove(link);
} finally {
if(nodeAdapter != null) nodeAdapter.notificationEnabled = oldNotify1;
}
}
}
}else{
List nodes = getDiagram().getNodes();
for (Iterator iter = nodes.iterator(); iter.hasNext();) {
ActivityNode element = (ActivityNode) iter.next();
if(element != getNode() && target instanceof MethodElement){
MethodElement me = BridgeHelper.getMethodElement(element);
if(me != null){
addIncomingConnection(me);
addOutgoingConnection(me);
}
}
}
}
}
protected MethodElementAdapter createMethodElementAdapter() {
return new WorkBreakdownElementAdapter();
}
@Override
protected void removeFromUMA(ActivityEdge link, ActivityNode oldSource,
ActivityNode oldTarget) {
org.eclipse.epf.uma.Activity diagramActivity = (org.eclipse.epf.uma.Activity) BridgeHelper.getMethodElement(getDiagram());
ProcessPackage pkg = (ProcessPackage) diagramActivity.eContainer();
MethodElement targetElement = BridgeHelper.getMethodElement(oldTarget);
if (targetElement instanceof WorkBreakdownElement) {
// this is a direct link
// remove WorkOrder
//
WorkBreakdownElement succ = (WorkBreakdownElement) targetElement;
if(diagramActivity != succ.getSuperActivities()) {
Object sourceElement = BridgeHelper.getMethodElement(oldSource);
if(sourceElement instanceof WorkBreakdownElement) {
WorkBreakdownElement pred = (WorkBreakdownElement) sourceElement;
WorkOrder order = ProcessUtil.findWorkOrder(diagramActivity, succ, pred);
if(order != null) {
getActionManager().doAction(IActionManager.REMOVE, pkg,
UmaPackage.Literals.PROCESS_PACKAGE__PROCESS_ELEMENTS, order, -1);
}
}
}
else {
NodeAdapter targetNodeAdapter = BridgeHelper.getNodeAdapter(oldTarget);
boolean notify = targetNodeAdapter != null ? targetNodeAdapter.notificationEnabled : false;
try {
if(targetNodeAdapter != null) {
targetNodeAdapter.notificationEnabled = false;
}
if (BridgeHelper.canRemoveAllPreds(link, oldSource,
oldTarget)) {
Object pred = BridgeHelper.getMethodElement(oldSource);
if(pred instanceof WorkBreakdownElement) {
WorkBreakdownElement e = (WorkBreakdownElement) BridgeHelper.getMethodElement(oldTarget);
Collection<WorkOrder> workOrders = UmaUtil.findWorkOrder(e, (WorkBreakdownElement) pred, true);
if(!workOrders.isEmpty()) {
getActionManager().doAction(IActionManager.REMOVE_MANY, e,
UmaPackage.Literals.WORK_BREAKDOWN_ELEMENT__LINK_TO_PREDECESSOR, workOrders, -1);
}
}
}
} finally {
if(targetNodeAdapter != null) {
targetNodeAdapter.notificationEnabled = notify;
}
}
}
} else if(oldTarget instanceof ControlNode && BridgeHelper.isSynchBar(oldTarget)) {
// get all the WorkBreakdownElementNodes that this synch bar is
// coming to and
// remove the WorkOrders with this WorkBreakdownElementNode's
// activity as predecessor from them
//
Collection<ActivityNode> actNodes = new ArrayList<ActivityNode>();
BridgeHelper.getSuccessorNodes(actNodes, oldTarget);
Object pred = BridgeHelper.getMethodElement(oldSource);
for (ActivityNode node : actNodes) {
WorkBreakdownElement e = (WorkBreakdownElement) BridgeHelper.getMethodElement(node);
if(diagramActivity == e.getSuperActivities()) {
NodeAdapter nodeAdapter = BridgeHelper.getNodeAdapter(node);
boolean notify = nodeAdapter != null ? nodeAdapter.notificationEnabled : false;
try {
if(nodeAdapter != null) {
nodeAdapter.notificationEnabled = false;
}
if (BridgeHelper.canRemoveAllPreds(link, oldSource, node)) {
WorkOrder wo;
while ((wo = UmaUtil.findWorkOrder(e, pred)) != null) {
getActionManager().doAction(IActionManager.REMOVE, e,
UmaPackage.Literals.WORK_BREAKDOWN_ELEMENT__LINK_TO_PREDECESSOR, wo, -1);
}
}
} finally {
if(nodeAdapter != null) {
nodeAdapter.notificationEnabled = notify;
}
}
}
else {
if(pred instanceof WorkBreakdownElement) {
// remove custom work order if there is any
//
WorkOrder wo = ProcessUtil.findWorkOrder(diagramActivity, e, (WorkBreakdownElement) pred);
if(wo != null) {
getActionManager().doAction(IActionManager.REMOVE, pkg,
UmaPackage.Literals.PROCESS_PACKAGE__PROCESS_ELEMENTS, wo, -1);
}
}
}
}
}
}
protected boolean addToUMA(final ActivityEdge link) {
if (!super.addToUMA(link))
return false;
MethodElement e = BridgeHelper.getMethodElement(link.getSource());
Activity diagramActivity = (Activity) BridgeHelper.getMethodElement(getDiagram());
ProcessPackage pkg = (ProcessPackage) diagramActivity.eContainer();
if (e instanceof WorkBreakdownElement) {
// this is a direct link
// add new WorkOrder object to UMA
//
WorkBreakdownElement succ = (WorkBreakdownElement) BridgeHelper.getMethodElement(link.getTarget());
WorkBreakdownElement pred = (WorkBreakdownElement) e;
WorkOrder order = addWorkOrder(link.getTarget(), succ, link.getSource(), pred, diagramActivity, link);
// set the WorkOrder as the element of the link's edge
// BridgeHelper.setSemanticModel(link, order);
}
else if (BridgeHelper.isSynchBar(link.getSource())) {
// get all WorkBreakdownElementNodes that are comming to this
// join node, both directly and indirectly
// and create work orders with their activity as predecessor
//
// Predecessor should be created only in case of
// Syncronization Bar, not for DecisionPoint.
// TODO: review
Collection actNodes = new ArrayList();
// Get the collection incoming connection of syncbar
// excluding decisionpoint incoming connection
BridgeHelper.getSyncBarSourceNodes(link.getSource(), actNodes);
WorkBreakdownElement succ = (WorkBreakdownElement) BridgeHelper.getMethodElement(link.getTarget());
for (Iterator<?> iter = actNodes.iterator(); iter.hasNext();) {
ActivityNode node = (ActivityNode) iter.next();
WorkBreakdownElement pred = (WorkBreakdownElement) BridgeHelper.getMethodElement(node);
addWorkOrder(link.getTarget(), succ, node, pred, diagramActivity, null);
}
}
return true;
}
protected ActivityEdge addIncomingConnection(MethodElement source) {
ActivityEdge link = super.addIncomingConnection(source);
if (link == null)
return link;
WorkOrder workOrder = UmaUtil.findWorkOrder(
(WorkBreakdownElement) getElement(), source);
BridgeHelper.setSemanticModel(link, workOrder);
return link;
}
protected ActivityEdge addOutgoingConnection(MethodElement target) {
ActivityEdge link = super.addOutgoingConnection(target);
WorkOrder workOrder = UmaUtil.findWorkOrder(
(WorkBreakdownElement) target, getElement());
BridgeHelper.setSemanticModel(link, workOrder);
return link;
}
protected boolean removeIncomingConnection(MethodElement source) {
// look for the incoming connection with source as linked object of the
// source node
//
for (ActivityEdge link : getNode().getIncomings()) {
if (link.getSource() != null
&& BridgeHelper.getMethodElement(link.getSource()) == source) {
// disable internal notification of the source node
//
NodeAdapter nodeAdapter = BridgeHelper.getNodeAdapter(link.getSource());
boolean oldNotify = nodeAdapter != null ? nodeAdapter.notificationEnabled : false;
try {
if(nodeAdapter != null) nodeAdapter.notificationEnabled = false;
link.setSource(null);
} finally {
if(nodeAdapter != null) nodeAdapter.notificationEnabled = oldNotify;
}
link.setTarget(null);
BridgeHelper.setSemanticModel(link, null);
getDiagram().getEdges().remove(link);
return true;
}
}
return false;
}
// @Override
// protected void handleNotification(Notification msg) {
// switch(msg.getFeatureID(ActivityParameterNode.class)) {
// case UMLPackage.ACTIVITY_PARAMETER_NODE__EANNOTATIONS:
// switch(msg.getEventType()) {
// case Notification.ADD:
// ActivityParameterNode node = (ActivityParameterNode) msg.getNotifier();
// String type = BridgeHelper.getType(node);
// MethodElement e = BridgeHelper.getMethodElement(node);
// if(e instanceof BreakdownElement &&
// type != null && !type.equals(BridgeHelper.getType(e))) {
// // replace the currently linked method element with the right one
// //
// EClass rightType = BridgeHelper.getType(type);
// if(rightType != null) {
// Object rightElement = UmaFactory.eINSTANCE.create(rightType);
// List list = ((BreakdownElement)e).getSuperActivities().getBreakdownElements();
// list.set(list.indexOf(e), rightElement);
// return;
// }
//
// }
// }
// }
//
// super.handleNotification(msg);
// }
}