//------------------------------------------------------------------------------ // 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); // } }