//------------------------------------------------------------------------------ // Copyright (c) 2005, 2006 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.model.impl; 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.AdapterFactory; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.edit.provider.ITreeItemContentProvider; import org.eclipse.epf.diagram.model.ActivityDiagram; import org.eclipse.epf.diagram.model.Link; import org.eclipse.epf.diagram.model.ModelFactory; import org.eclipse.epf.diagram.model.ModelPackage; import org.eclipse.epf.diagram.model.Node; import org.eclipse.epf.diagram.model.TypedNode; import org.eclipse.epf.diagram.model.util.GraphicalDataHelper; import org.eclipse.epf.diagram.model.util.IActivityDiagramChangeListener; import org.eclipse.epf.diagram.model.util.IAdapterFactoryFilter; import org.eclipse.epf.library.edit.TngAdapterFactory; import org.eclipse.epf.library.edit.process.ActivityWrapperItemProvider; import org.eclipse.epf.library.edit.process.BSActivityItemProvider; import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider; import org.eclipse.epf.library.edit.process.IBSItemProvider; import org.eclipse.epf.library.edit.process.WBSActivityItemProvider; import org.eclipse.epf.library.edit.util.ConfigurableComposedAdapterFactory; import org.eclipse.epf.library.edit.util.TngUtil; import org.eclipse.epf.uma.Activity; import org.eclipse.epf.uma.BreakdownElement; import org.eclipse.epf.uma.GraphEdge; import org.eclipse.epf.uma.GraphNode; import org.eclipse.epf.uma.MethodElement; import org.eclipse.epf.uma.SemanticModelBridge; import org.eclipse.epf.uma.SimpleSemanticModelElement; import org.eclipse.epf.uma.UMASemanticModelBridge; import org.eclipse.epf.uma.VariabilityElement; import org.eclipse.epf.uma.WorkBreakdownElement; import org.eclipse.epf.uma.WorkOrder; /** * <!-- begin-user-doc --> An implementation of the model object '<em><b>Activity Diagram</b></em>'. * <!-- end-user-doc --> * <p> * </p> * * @generated */ public class ActivityDiagramImpl extends DiagramImpl implements ActivityDiagram { private class ActivityDiagramChangeListener extends ActivityAdapter implements IActivityDiagramChangeListener { }; /** * <!-- begin-user-doc --> <!-- end-user-doc --> */ protected ActivityDiagramImpl() { super(); diagramChangeListener = new ActivityDiagramChangeListener(); } protected Class getDiagramChangeListenerType() { return IActivityDiagramChangeListener.class; } /** * <!-- begin-user-doc --> <!-- end-user-doc --> * @generated */ @Override protected EClass eStaticClass() { return ModelPackage.Literals.ACTIVITY_DIAGRAM; } protected void populateNodes() { // Activity act = (Activity) getObject(); org.eclipse.epf.uma.Diagram diagram = getUMADiagram(); // add TypedNodes // List typedNodes = new ArrayList(); for (Iterator iter = diagram.getContained().iterator(); iter.hasNext();) { Object element = iter.next(); int type = getType(element); if (type > 0) { TypedNode node = ModelFactory.eINSTANCE.createTypedNode(); node.setType(type); node.setObject(element); typedNodes.add(node); } } getNodes().addAll(typedNodes); // add WorkBreakdownElementNodes // addElementNodes(); } private static boolean isValidWorkOrder(WorkOrder wo, Object pred) { if (wo.getPred() == pred) { return true; } if (pred instanceof Activity) { Activity act = (Activity) pred; // check if predecessor reference in the given work order is base of // pred // for (VariabilityElement ve = act.getVariabilityBasedOnElement(); ve != null; ve = ve .getVariabilityBasedOnElement()) { if (ve == wo.getPred()) { return true; } } } return false; } private boolean isValid(Link link) { if (link.getSource() == null || link.getTarget() == null || !getNodes().contains(link.getSource()) || !getNodes().contains(link.getTarget())) { return false; } return true; } protected void populateLinks() { super.populateLinks(); // remove the invalid links // for (Iterator iter = getNodes().iterator(); iter.hasNext();) { Node node = ((Node) iter.next()); WorkBreakdownElement wbe = null; if (node.getObject() instanceof WorkBreakdownElement) { wbe = (WorkBreakdownElement) node.getObject(); } ArrayList linksToRemove = new ArrayList(); linkListWalk: for (Iterator iterator = node .getIncomingConnections().iterator(); iterator.hasNext();) { Link link = (Link) iterator.next(); if (!isValid(link)) { linksToRemove.add(link); } if (wbe != null) { // TODO: need revisit to check the valid connection from a // TypedNode // if (link.getSource() instanceof TypedNode) continue linkListWalk; Object pred = link.getSource().getObject(); boolean workOrderFound = false; find_WorkOrder: for (Iterator iterator1 = wbe .getLinkToPredecessor().iterator(); iterator1 .hasNext();) { WorkOrder wo = (WorkOrder) iterator1.next(); if (isValidWorkOrder(wo, pred)) { workOrderFound = true; break find_WorkOrder; } } if (!workOrderFound) { // invalid link, remove it // linksToRemove.add(link); } } } for (Iterator iterator = linksToRemove.iterator(); iterator .hasNext();) { Link link = (Link) iterator.next(); GraphicalDataHelper.removeLink(link); } linksToRemove.clear(); for (Iterator iterator = node.getOutgoingConnections().iterator(); iterator .hasNext();) { Link link = (Link) iterator.next(); if (!isValid(link)) { linksToRemove.add(link); } } for (Iterator iterator = linksToRemove.iterator(); iterator .hasNext();) { Link link = (Link) iterator.next(); GraphicalDataHelper.removeLink(link); } linksToRemove.clear(); linksToRemove = null; } // Check the links of each ActivityNode // set the WorkOrder to the link if needed // add new link for those WorkOrders that still don't have the // corresponding link // AdapterFactory adapterFactory = getAdapterFactory(); for (Iterator iter = getNodes().iterator(); iter.hasNext();) { Node node = ((Node) iter.next()); if (node.getObject() instanceof WorkBreakdownElement) { List list = new ArrayList(); // Get the raw data of workorders for object. WorkBreakdownElement local = (WorkBreakdownElement) node.getObject(); list.addAll(local.getLinkToPredecessor()); // Get the Predecessor List on top of raw data, this is need for in case of extend. ITreeItemContentProvider adapter = null; adapter = (ITreeItemContentProvider)adapterFactory .adapt(local, ITreeItemContentProvider.class); if(adapter instanceof IBSItemProvider){ list.addAll(((IBSItemProvider)adapter).getPredecessors()); } // Iterate work orders and create links. for (Iterator iterator = list.iterator(); iterator .hasNext();) { Object next = iterator.next(); WorkOrder workOrder = null; BreakdownElement pred = null; if(next instanceof WorkOrder){ workOrder = (WorkOrder)next; pred = workOrder.getPred(); } if(next instanceof WBSActivityItemProvider){ pred = (BreakdownElement)((WBSActivityItemProvider)next).getTarget(); } if (pred != null && pred instanceof WorkBreakdownElement) { Node predNode = GraphicalDataHelper.findNode(this, pred, true); if (predNode != null) { // check if there is a link for this work order // already // boolean linkFound = false; find_link: for (Iterator iterator1 = node .getIncomingConnections().iterator(); iterator1 .hasNext();) { Link link = (Link) iterator1.next(); if (link.getSource() == predNode) { // link already exists // check if work order is set to this link // linkFound = true; GraphEdge edge = (GraphEdge) link .getObject(); if (edge.getSemanticModel() == null) { GraphicalDataHelper.setSemanticModel( link, workOrder); } break find_link; } } if (!linkFound) { // check if this WorkOrder can be represented // via links of TypedNodes // if (!canReachAsFirstActivityNode(predNode, node)) { // add new link for this work order // NamedNodeImpl nodeImpl = ((NamedNodeImpl) node); NamedNodeImpl predNodeImpl = (NamedNodeImpl) predNode; boolean oldNotify = nodeImpl.notificationEnabled; boolean predNodeNotify = predNodeImpl.notificationEnabled; try { nodeImpl.notificationEnabled = false; predNodeImpl.notificationEnabled = false; nodeImpl.addIncomingConnection(pred); } finally { nodeImpl.notificationEnabled = oldNotify; predNodeImpl.notificationEnabled = predNodeNotify; } } } } } } } } cleanDuplicateLinks(); } private void cleanDuplicateLinks() { List duplicateLinks = new ArrayList(); for (Iterator iter = getNodes().iterator(); iter.hasNext();) { Object node = iter.next(); if (node instanceof Node) { Node wbNode = (Node) node; if(wbNode.getIncomingConnections() != null){ findDuplicateLinks(duplicateLinks, wbNode.getIncomingConnections()); } if(wbNode.getOutgoingConnections() !=null){ findDuplicateLinks(duplicateLinks, wbNode.getOutgoingConnections()); } } } for (Iterator iterator = duplicateLinks.iterator(); iterator.hasNext();) { Link link = (Link) iterator.next(); GraphicalDataHelper.removeLink(link); } duplicateLinks.clear(); duplicateLinks = null; } private void findDuplicateLinks(List duplicateLinks, List links) { for (int i = 0; i < links.size(); i++) { Link link = (Link) links.get(i); if(!duplicateLinks.contains(link)){ for (int j = i + 1; j < links.size(); j++) { Link link1 = (Link) links.get(j); if (link1.getSource() == link.getSource() && link1.getTarget() == link.getTarget()) { duplicateLinks.add(link1); } } } } } /** * Checks if Node src can reach Node target as the first ActivityNode in the * diagram * * @param src * @param target * @return */ private static boolean canReachAsFirstActivityNode(Node src, Node target) { for (Iterator iter = src.getOutgoingConnections().iterator(); iter .hasNext();) { Link link = (Link) iter.next(); if (link.getTarget() == target) { return true; } if (link.getTarget() instanceof TypedNode && canReachAsFirstActivityNode(link.getTarget(), target)) { return true; } } return false; } // private List toNodes(List activities) { // List list = new ArrayList(); // for (Iterator iter = activities.iterator(); iter.hasNext();) { // list.add(toNode((MethodElement) iter.next())); // } // return list; // } /* * (non-Javadoc) * * @see org.eclipse.epf.diagram.model.impl.DiagramImpl#newNode() */ protected Node newNode() { return ModelFactory.eINSTANCE.createWorkBreakdownElementNode(); } public Collection getChildren() { ITreeItemContentProvider adapter = getAdapter(); if (adapter != null) { //Turn off the VariabilityInfo for the activity diagram. Object obj = null; boolean enableVariabilityInfo = false; if(adapter instanceof ActivityWrapperItemProvider){ obj = ((ActivityWrapperItemProvider)adapter).getDelegatingItemProvider(); } if(adapter instanceof BSActivityItemProvider){ obj = adapter; } if(obj instanceof BSActivityItemProvider){ enableVariabilityInfo = ((BSActivityItemProvider)obj).isEnableVariabilityInfo(); ((BSActivityItemProvider)obj).setEnableVariabilityInfo(false); } // end of variability info // return adapter.getChildren(getObject()); // commented above line, For diagrams - rollup should be false, for // handling rollup state below code. List children = new ArrayList(); extractChildren(adapter, getObject(), children, true); // reset variabilityinfo status back if(obj instanceof BSActivityItemProvider){ ((BSActivityItemProvider)obj).setEnableVariabilityInfo(enableVariabilityInfo); } return children; } else { return Collections.EMPTY_LIST; } } private void addElementNodes() { ArrayList nodes = new ArrayList(); for (Iterator iter = getChildren().iterator(); iter.hasNext();) { Object e = iter.next(); Object child = TngUtil.unwrap(e); if (child instanceof WorkBreakdownElement) { NamedNodeImpl node = (NamedNodeImpl) toNode((MethodElement) child); if (e instanceof BreakdownElementWrapperItemProvider) { BreakdownElementWrapperItemProvider wrapper = ((BreakdownElementWrapperItemProvider) e); if (wrapper.isReadOnly()) { node.itemProvider = wrapper; // TODO: check if readOnly attribute is still needed // after introduction of itemProvider // node.readOnly = true; } } nodes.add(node); } } getNodes().addAll(nodes); } private static int getType(Object obj) { if (obj instanceof GraphNode) { GraphNode node = (GraphNode) obj; SemanticModelBridge modelBridge = node.getSemanticModel(); if (modelBridge instanceof SimpleSemanticModelElement) { String type = ((SimpleSemanticModelElement) modelBridge) .getTypeInfo(); if (GraphicalDataHelper.GRAPH_NODE_SYNCH_BAR.equals(type)) { return TypedNode.SYNCH_BAR; } else if (GraphicalDataHelper.GRAPH_NODE_DECISION.equals(type)) { return TypedNode.DECISION; } else if (GraphicalDataHelper.GRAPH_NODE_END.equals(type)) { return TypedNode.END; } else if (GraphicalDataHelper.GRAPH_NODE_START.equals(type)) { return TypedNode.START; } else if (GraphicalDataHelper.GRAPH_NODE_FREE_TEXT .equals(type)) { return TypedNode.FREE_TEXT; } } } return -1; } protected int getType() { return GraphicalDataHelper.ACTIVITY_DIAGRAM; } protected List getBreakdownElementTypes() { return Collections.singletonList(WorkBreakdownElement.class); } private int toActivityIndex(int index) { if (index == -1) return index; int size = getNodes().size(); int i = index + 1; if (i == size) return -1; Node node = (Node) getNodes().get(i); if (node == null) return -1; for (; !(node.getObject() instanceof BreakdownElement) && i < size; i++) { node = (Node) getNodes().get(i); } if (i == size) return -1; Activity act = (Activity) getObject(); return act.getBreakdownElements().indexOf(node.getObject()); } /* * (non-Javadoc) * * @see org.eclipse.epf.diagram.model.impl.DiagramImpl#addToUmaModel(int, * org.eclipse.epf.diagram.model.Node) */ protected void addToUmaModel(int position, Node addedNode) { if (addedNode.getObject() instanceof BreakdownElement) { Activity act = (Activity) getObject(); // translate ActivityNode index to Activity index // int i = toActivityIndex(position); // System.out.println("DiagramImpl.addToUmaModel(): // WorkBreakdownElement index: " + i); if (i == -1) { act.getBreakdownElements().add((BreakdownElement) addedNode.getObject()); } else { act.getBreakdownElements().add(i, (BreakdownElement) addedNode.getObject()); } } super.addToUmaModel(position, addedNode); } /* * (non-Javadoc) * * @see org.eclipse.epf.diagram.model.impl.DiagramImpl#addNode(java.util.Collection, * java.lang.Object) */ protected Node addNode(Collection nodes, Object obj) { if (obj instanceof Activity) { Activity act = (Activity) obj; VariabilityElement base = act.getVariabilityBasedOnElement(); if (base != null) { // find existing node for base and link it to the activity // NodeImpl baseNode = (NodeImpl) GraphicalDataHelper.findNode( this, base); if (baseNode != null) { GraphNode graphNode = baseNode.getGraphNode(); UMASemanticModelBridge bridge = (UMASemanticModelBridge) graphNode .getSemanticModel(); if (bridge.getElement() != act) { bridge.setElement(act); } } else { baseNode = (NodeImpl) GraphicalDataHelper.findNode(this, act); } if (baseNode != null) { // disassociate with the base // if (baseNode.methodElementAdapter != null) { base.eAdapters().remove(baseNode.methodElementAdapter); } baseNode.basicSetObject(act); baseNode.setReadOnly(false); return null; } } } return super.addNode(nodes, obj); } /* * (non-Javadoc) * * @see org.eclipse.epf.diagram.model.impl.DiagramImpl#removeNode(java.lang.Object) */ protected boolean removeNode(Object obj) { if (obj instanceof Activity) { Activity act = (Activity) obj; VariabilityElement base = act.getVariabilityBasedOnElement(); if (base != null) { // find existing node for the old activity and relink it to its // base // NodeImpl node = (NodeImpl) GraphicalDataHelper.findNode(this, act); if (node != null) { GraphNode graphNode = node.getGraphNode(); UMASemanticModelBridge bridge = (UMASemanticModelBridge) graphNode .getSemanticModel(); if (bridge.getElement() != base) { bridge.setElement(base); } } else { node = (NodeImpl) GraphicalDataHelper.findNode(this, base); } if (node != null) { // disassociate with the old activity // if (node.methodElementAdapter != null) { act.eAdapters().remove(node.methodElementAdapter); } node.basicSetObject(base); node.setReadOnly(true); return false; } } } return super.removeNode(obj); } /** * Moved code from getChildren. getAdapter() will return Adapter, * which will allow us to find itemprovider for the children. * * @return */ private ITreeItemContentProvider getAdapter(){ ITreeItemContentProvider adapter = null; if (wrapper != null) { adapter = wrapper; } else { adapter =(ITreeItemContentProvider)getAdapterFactory().adapt( getObject(), ITreeItemContentProvider.class); } return adapter; } private AdapterFactory getAdapterFactory(){ AdapterFactory adapterFactory = null; if (filter == null) { adapterFactory = TngAdapterFactory.INSTANCE.getWBS_ComposedAdapterFactory(); } else if (filter instanceof IAdapterFactoryFilter) { adapterFactory = (ConfigurableComposedAdapterFactory) ((IAdapterFactoryFilter) filter) .getWBSAdapterFactory(); } return adapterFactory; } } // ActivityDiagramImpl