//------------------------------------------------------------------------------
// 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.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.epf.diagram.model.ActivityDetailDiagram;
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.NodeContainer;
import org.eclipse.epf.diagram.model.RoleNode;
import org.eclipse.epf.diagram.model.RoleTaskComposite;
import org.eclipse.epf.diagram.model.TaskNode;
import org.eclipse.epf.diagram.model.WorkProductComposite;
import org.eclipse.epf.diagram.model.util.GraphicalDataHelper;
import org.eclipse.epf.diagram.model.util.GraphicalDataManager;
import org.eclipse.epf.diagram.model.util.INodeChangeListener;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Diagram;
import org.eclipse.epf.uma.GraphNode;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.Property;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.UMASemanticModelBridge;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.ecore.util.OppositeFeatureNotification;
import org.eclipse.epf.uma.util.AssociationHelper;


/**
 * <!-- begin-user-doc --> An implementation of the model object '<em><b>Role Task Composite</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * </p>
 * 
 * @generated
 */
public class RoleTaskCompositeImpl extends NodeContainerImpl implements
		RoleTaskComposite {
	
	private int rowIndex;
	
	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 */
	protected RoleTaskCompositeImpl() {
		super();

		methodElementAdapter = new RoleDescriptorAdapter();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	protected EClass eStaticClass() {
		return ModelPackage.eINSTANCE.getRoleTaskComposite();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public NotificationChain eInverseAdd(InternalEObject otherEnd,
			int featureID, Class baseClass, NotificationChain msgs) {
		if (featureID >= 0) {
			switch (eDerivedStructuralFeatureID(featureID, baseClass)) {
			case ModelPackage.ROLE_TASK_COMPOSITE__INCOMING_CONNECTIONS:
				return ((InternalEList) getIncomingConnections()).basicAdd(
						otherEnd, msgs);
			case ModelPackage.ROLE_TASK_COMPOSITE__OUTGOING_CONNECTIONS:
				return ((InternalEList) getOutgoingConnections()).basicAdd(
						otherEnd, msgs);
			default:
				return eDynamicInverseAdd(otherEnd, featureID, baseClass, msgs);
			}
		}
		if (eContainer != null)
			msgs = eBasicRemoveFromContainer(msgs);
		return eBasicSetContainer(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public NotificationChain eInverseRemove(InternalEObject otherEnd,
			int featureID, Class baseClass, NotificationChain msgs) {
		if (featureID >= 0) {
			switch (eDerivedStructuralFeatureID(featureID, baseClass)) {
			case ModelPackage.ROLE_TASK_COMPOSITE__INCOMING_CONNECTIONS:
				return ((InternalEList) getIncomingConnections()).basicRemove(
						otherEnd, msgs);
			case ModelPackage.ROLE_TASK_COMPOSITE__OUTGOING_CONNECTIONS:
				return ((InternalEList) getOutgoingConnections()).basicRemove(
						otherEnd, msgs);
			case ModelPackage.ROLE_TASK_COMPOSITE__NODES:
				return ((InternalEList) getNodes()).basicRemove(otherEnd, msgs);
			default:
				return eDynamicInverseRemove(otherEnd, featureID, baseClass,
						msgs);
			}
		}
		return eBasicSetContainer(null, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public Object eGet(EStructuralFeature eFeature, boolean resolve) {
		switch (eDerivedStructuralFeatureID(eFeature)) {
		case ModelPackage.ROLE_TASK_COMPOSITE__OBJECT:
			return getObject();
		case ModelPackage.ROLE_TASK_COMPOSITE__LOCATION:
			return getLocation();
		case ModelPackage.ROLE_TASK_COMPOSITE__WIDTH:
			return new Integer(getWidth());
		case ModelPackage.ROLE_TASK_COMPOSITE__HEIGHT:
			return new Integer(getHeight());
		case ModelPackage.ROLE_TASK_COMPOSITE__INCOMING_CONNECTIONS:
			return getIncomingConnections();
		case ModelPackage.ROLE_TASK_COMPOSITE__OUTGOING_CONNECTIONS:
			return getOutgoingConnections();
		case ModelPackage.ROLE_TASK_COMPOSITE__READ_ONLY:
			return isReadOnly() ? Boolean.TRUE : Boolean.FALSE;
		case ModelPackage.ROLE_TASK_COMPOSITE__NODES:
			return getNodes();
		}
		return eDynamicGet(eFeature, resolve);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public void eSet(EStructuralFeature eFeature, Object newValue) {
		switch (eDerivedStructuralFeatureID(eFeature)) {
		case ModelPackage.ROLE_TASK_COMPOSITE__OBJECT:
			setObject((Object) newValue);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__LOCATION:
			setLocation((Point) newValue);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__WIDTH:
			setWidth(((Integer) newValue).intValue());
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__HEIGHT:
			setHeight(((Integer) newValue).intValue());
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__INCOMING_CONNECTIONS:
			getIncomingConnections().clear();
			getIncomingConnections().addAll((Collection) newValue);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__OUTGOING_CONNECTIONS:
			getOutgoingConnections().clear();
			getOutgoingConnections().addAll((Collection) newValue);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__READ_ONLY:
			setReadOnly(((Boolean) newValue).booleanValue());
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__NODES:
			getNodes().clear();
			getNodes().addAll((Collection) newValue);
			return;
		}
		eDynamicSet(eFeature, newValue);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public void eUnset(EStructuralFeature eFeature) {
		switch (eDerivedStructuralFeatureID(eFeature)) {
		case ModelPackage.ROLE_TASK_COMPOSITE__OBJECT:
			setObject(OBJECT_EDEFAULT);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__LOCATION:
			setLocation(LOCATION_EDEFAULT);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__WIDTH:
			setWidth(WIDTH_EDEFAULT);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__HEIGHT:
			setHeight(HEIGHT_EDEFAULT);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__INCOMING_CONNECTIONS:
			getIncomingConnections().clear();
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__OUTGOING_CONNECTIONS:
			getOutgoingConnections().clear();
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__READ_ONLY:
			setReadOnly(READ_ONLY_EDEFAULT);
			return;
		case ModelPackage.ROLE_TASK_COMPOSITE__NODES:
			getNodes().clear();
			return;
		}
		eDynamicUnset(eFeature);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public boolean eIsSet(EStructuralFeature eFeature) {
		switch (eDerivedStructuralFeatureID(eFeature)) {
		case ModelPackage.ROLE_TASK_COMPOSITE__OBJECT:
			return OBJECT_EDEFAULT == null ? object != null : !OBJECT_EDEFAULT
					.equals(object);
		case ModelPackage.ROLE_TASK_COMPOSITE__LOCATION:
			return LOCATION_EDEFAULT == null ? location != null
					: !LOCATION_EDEFAULT.equals(location);
		case ModelPackage.ROLE_TASK_COMPOSITE__WIDTH:
			return width != WIDTH_EDEFAULT;
		case ModelPackage.ROLE_TASK_COMPOSITE__HEIGHT:
			return height != HEIGHT_EDEFAULT;
		case ModelPackage.ROLE_TASK_COMPOSITE__INCOMING_CONNECTIONS:
			return incomingConnections != null
					&& !incomingConnections.isEmpty();
		case ModelPackage.ROLE_TASK_COMPOSITE__OUTGOING_CONNECTIONS:
			return outgoingConnections != null
					&& !outgoingConnections.isEmpty();
		case ModelPackage.ROLE_TASK_COMPOSITE__READ_ONLY:
			return readOnly != READ_ONLY_EDEFAULT;
		case ModelPackage.ROLE_TASK_COMPOSITE__NODES:
			return nodes != null && !nodes.isEmpty();
		}
		return eDynamicIsSet(eFeature);
	}

	private static boolean contains(Collection mixedCollection, Object element) {
		for (Iterator iter = mixedCollection.iterator(); iter.hasNext();) {
			if( element == TngUtil.unwrap(iter.next()) ) {
				return true;
			}		
		}
		return false;
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.diagram.model.impl.NodeImpl#setObject(java.lang.Object)
	 */
	public void setObject(Object newObject) {
		super.setObject(newObject);
		populateNodes(newObject);
//		if (newObject instanceof RoleDescriptor) {
//			RoleDescriptor roleDescriptor = (RoleDescriptor) newObject;
//			ActivityDetailDiagramImpl diagram = (ActivityDetailDiagramImpl) getDiagram();
//			Collection allElements = diagram.getAllBreakdownElements();
//			List primaryTaskDescriptors = AssociationHelper.getPrimaryTaskDescriptors(roleDescriptor);
//			if (!primaryTaskDescriptors.isEmpty()) { // overriding
//																	
//				// use list to maintain order of
//				// taskdescriptors.
//				List taskDescriptors = new ArrayList();
//				taskDescriptors.addAll(primaryTaskDescriptors);
//				// taskDescriptors.addAll(roleDescriptor.getPerformsAdditionally());
//				// taskDescriptors.addAll(roleDescriptor.getAssistsIn());
//
//				HashSet selectedDescriptors = new HashSet();
//				List taskNodes = new ArrayList();
//				
//				String autolayout = GraphicalDataHelper.getAutoLayoutFlag((ActivityDetailDiagram)getDiagram()); 
//				if(autolayout != null){
//					int index = 0;
//					for (Iterator iter = allElements.iterator(); iter.hasNext();) {
//						Object obj = iter.next();
//						obj = TngUtil.unwrap(obj);
//						if (obj instanceof TaskDescriptor
//								&& TngUtil.contains(taskDescriptors, obj)) {
//							TaskDescriptor taskDescriptor = (TaskDescriptor) obj;
//
//							// eliminate descriptor that is duplicate,
//							// suppressed or filtered out
//							//
//							if (!selectedDescriptors.contains(taskDescriptor)
//							// && contains(allElements, taskDescriptor) // make
//							// sure that task descriptor is of the owning
//							// activity
//							) {
//								selectedDescriptors.add(taskDescriptor);
//								Node node = GraphicalDataHelper.findNode(
//										this, taskDescriptor,
//										TaskNode.class);
//								if (node == null) {
//									node = ModelFactory.eINSTANCE
//											.createTaskNode();
//									node.setDiagram(getDiagram());
//									node.setObject(taskDescriptor);
//									((NamedNodeImpl) node)
//											.setItemProvider(allElements);
//									if(GraphicalDataHelper.findProperty(node.getGraphNode(), 
//											GraphicalDataHelper.PROP_INDEX) == null
//											|| GraphicalDataHelper.isAutoLayout((ActivityDetailDiagram)getDiagram())){
//										GraphicalDataHelper.createProperty(node
//											.getGraphNode(),
//											GraphicalDataHelper.PROP_INDEX,
//											new Integer(index).toString());
//										index++;
//									}
//									
//								}
//								taskNodes.add(node);
//							}
//						}
//					}
//					// Sort the taskNode based on their index if autolayout is
//					// false
//					if (GraphicalDataHelper.PROP_AUTO_LAYOUT_VALUE_FALSE
//							.equals(autolayout)) {
//						Collections.sort(taskNodes, comparator);
//					}
//			  }else{
//					for (Iterator iter = taskDescriptors.iterator(); iter.hasNext();) {
//						TaskDescriptor taskDescriptor = (TaskDescriptor) iter.next();
//						
//						// eliminate descriptor that is duplicate, suppressed or filtered out
//						//
//						if(!selectedDescriptors.contains(taskDescriptor)
//								&& contains(allElements, taskDescriptor) // make sure that task descriptor is of the owning activity
//						) {
//							selectedDescriptors.add(taskDescriptor);					
//						Node node = GraphicalDataHelper.findNode(getDiagram(),
//									taskDescriptor, TaskNode.class);
//						if (node == null) {
//							node = ModelFactory.eINSTANCE.createTaskNode();
//							node.setDiagram(getDiagram());
//							node.setObject(taskDescriptor);
//							((NamedNodeImpl) node).setItemProvider(allElements);
//						}
//						taskNodes.add(node);
//						}
//					}
//				}
//				if(!taskNodes.isEmpty()) {
//					// add role node
//					//
//					Node node = (NamedNodeImpl) ModelFactory.eINSTANCE.createRoleNode();
//					node.setDiagram(getDiagram());
//					node.setObject(roleDescriptor);
//					((NamedNodeImpl) node).setItemProvider(allElements);
//					getNodes().add(node);
//					// add task nodes
//					//
//					getNodes().addAll(taskNodes);
//				}
//			}
//		}

		
	}
	public GraphNode getGraphNode(MethodElement methodElement) {
		if (getUMADiagram() == null) {
			// new MethodElement
			//
			return GraphicalDataManager.getInstance().createGraphNode(methodElement);
		}
		GraphNode node = findGraphNode(getUMADiagram(), methodElement);
		if (node == null) {
			node = GraphicalDataManager.getInstance().createGraphNode(methodElement);
			// createGraphConnectors(node, getUMADiagram());
			getUMADiagram().getContained().add(node);
		}
		String autolayout = GraphicalDataHelper.getAutoLayoutFlag((ActivityDetailDiagram)getDiagram());
		if(autolayout != null){
			GraphicalDataHelper.createProperty(node, GraphicalDataHelper.PROP_INDEX, new Integer(rowIndex).toString());
		}
		return node;
	}

	public GraphNode findGraphNode(Diagram diagram, Object methodElement) {
		for (Iterator iter = diagram.getContained().iterator(); iter.hasNext();) {
			GraphNode element = (GraphNode) iter.next();
			if (element.getSemanticModel() instanceof UMASemanticModelBridge
					&& methodElement == ((UMASemanticModelBridge) element
							.getSemanticModel()).getElement()) {

				Property property = GraphicalDataHelper.findProperty(element, GraphicalDataHelper.PROP_INDEX);
				
				if (property != null) {
					String index = property.getValue();
					if (index != null) {
						if (getRowIndex() == new Integer(index).intValue())
							return element;
					}
				}else{
					return element;
				}
			}
		}
		return null;
	}
	
	public GraphNode createGraphNode(MethodElement element) {
		GraphNode node = GraphicalDataManager.getInstance().createGraphNode(element);
		GraphicalDataHelper.createProperty(node,
				GraphicalDataHelper.PROP_INDEX, new Integer(rowIndex)
						.toString());
		return node;
	}
	private class RoleDescriptorAdapter extends AdapterImpl implements
			INodeChangeListener {
		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.eclipse.emf.common.notify.Notification)
		 */
		public void notifyChanged(Notification msg) {
			if(msg instanceof OppositeFeatureNotification) {
				Object feature = ((OppositeFeatureNotification)msg).getOppsiteFeature();
				if(feature == AssociationHelper.RoleDescriptor_PrimaryTaskDescriptors) {
					switch (msg.getEventType()) {
					case Notification.ADD:
						addNode((TaskDescriptor) msg.getNewValue());
						return;
					case Notification.REMOVE:
						removeNode(msg.getOldValue());
						return;
					case Notification.ADD_MANY:
						addNode((Collection) msg.getNewValue());
						return;
					case Notification.REMOVE_MANY:
						removeNode((Collection) msg.getOldValue());
						return;
					}
				}
			}
			switch (msg.getFeatureID(Activity.class)) {
			case UmaPackage.ACTIVITY__BREAKDOWN_ELEMENTS:
				switch (msg.getEventType()) {
				case Notification.MOVE:
					System.out.println("MOVEEEEEEED");
					break;
				}
				break;
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.epf.diagram.model.util.INodeChangeListener#getNode()
		 */
		public Node getNode() {
			return RoleTaskCompositeImpl.this;
		}

	}

	/**
	 * @param oldValue
	 */
	private void removeNode(Object oldValue) {
		Collection removedNodes = new HashSet();
		for (Iterator iter = nodes.iterator(); iter.hasNext();) {
			Node node = (Node) iter.next();
			if (oldValue instanceof TaskDescriptor) {
				if (node instanceof RoleNode) {
					ActivityDetailDiagramImpl d = (ActivityDetailDiagramImpl)getDiagram();
					List list = //AssociationHelper.getPrimaryTaskDescriptors((RoleDescriptor) node.getObject());
						d.getRealizedPrimaryTaskDescriptors((RoleDescriptor) node.getObject());
					if (list == null || list.size() < 1) {
						iter.remove();
						removedNodes.add(node);
					}
				}
			}
			if (node.getObject() == oldValue) {
				iter.remove();
				removedNodes.add(node);
				if (oldValue instanceof TaskDescriptor) {
					Node wpnode = GraphicalDataHelper.findNode(
							(ActivityDetailDiagram) getDiagram(), oldValue);
					getDiagram().getNodes().remove(wpnode);
					wpnode = GraphicalDataHelper.findNode(
							(ActivityDetailDiagram) getDiagram(), oldValue);
					getDiagram().getNodes().remove(wpnode);
				}
			}
		}
		if (nodes.isEmpty()) {
			getDiagram().getNodes().remove(this);
		}
		// pushBackToDiagram(removedNodes);
	}

	/**
	 * @param descriptor
	 */
	private void addNode(TaskDescriptor descriptor) {
		addNode(getNodes(), descriptor);
	}

	private void addNode(Collection nodes, TaskDescriptor descriptor) {

		ActivityDetailDiagramImpl diagram = (ActivityDetailDiagramImpl) getDiagram();
		Node node = GraphicalDataHelper.findNode((NodeContainer) diagram,
				descriptor);
		if (node == null) {
			if (descriptor instanceof TaskDescriptor) {
				RoleDescriptor roleDescriptor = ((TaskDescriptor) descriptor)
						.getPerformedPrimarilyBy();
				Node roleNode = ((ActivityDetailDiagramImpl) getDiagram()).findNode(
						(ActivityDetailDiagram) getDiagram(), roleDescriptor);
				if (roleNode == null) {
					roleNode = ((ActivityDetailDiagramImpl) getDiagram())
							.createRoleTaskComposite(roleDescriptor);
					getDiagram().getNodes().add(roleNode);
				} else {
					node = diagram.createNode(descriptor);
					int i = getNextIndex(getNodes());
					if(node instanceof TaskNode){
						GraphicalDataHelper.createProperty(node.getGraphNode(), 
							GraphicalDataHelper.PROP_INDEX, new Integer(i+1).toString());
					}
					//createTaskInputOutputNodes(descriptor, getDiagram().getNodes());
				}
			}
		}
		if(node != null){
			nodes.add(node);
		}
	}

	/**
	 * @param oldValue
	 */
	private void removeNode(Collection elements) {
		Collection nodes = new ArrayList();
		for (Iterator iter = nodes.iterator(); iter.hasNext();) {
			Node node = (Node) iter.next();
			if (elements.contains(node.getObject())) {
				nodes.add(node);
			}
		}
		getNodes().removeAll(nodes);
		// pushBackToDiagram(nodes);
	}

	/**
	 * @param newValue
	 */
	private void addNode(Collection elements) {
		Collection nodes = new ArrayList();
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			TaskDescriptor descriptor = (TaskDescriptor) iter.next();
			addNode(nodes, descriptor);
		}

		getNodes().addAll(nodes);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.diagram.model.impl.NodeImpl#getMethodElementAdapterType()
	 */
	public Class getMethodElementAdapterType() {
		return RoleDescriptorAdapter.class;
	}
	
	/**
	 * @return
	 */
	private int getNextIndex(List nodes) {
		int index = 0;
		for(Iterator iterator = nodes.iterator(); iterator.hasNext();){
			Object obj = iterator.next();
			if(obj instanceof Node){
				Node node = (Node)obj;
				//String temp = GraphicalDataHelper.findProperty(node.getGraphNode(), GraphicalDataHelper.PROP_INDEX).getValue();
				List list = node.getGraphNode().getList(UmaPackage.GRAPH_NODE__PROPERTY);
				if(list != null && !list.isEmpty()){
					for (int i = list.size() - 1; i > -1; i--) {
						Property prop = (Property) list.get(i);
						if (GraphicalDataHelper.PROP_INDEX.equals(prop.getKey())){
							int temp  = Integer.parseInt(prop.getValue());
							if(temp > index ) index = temp;
						}
					}
				}
			}
		}
		return index;
	}
	
	private static final Comparator comparator = new Comparator() {

		public int compare(Object obj1, Object obj2) {
			if (obj1 == obj2)
				return 0;
			if(obj1 instanceof Node && obj2 instanceof Node){
				Node node1 = (Node)obj1;
				Node node2 = (Node)obj2;
				if(getIndex(node1) >  getIndex(node2))
					return 1;
			}
			return 0;
		}

	};
	/**
	 * 
	 */
	private static int getIndex(Node node) {
		String temp = getProperty(node, GraphicalDataHelper.PROP_INDEX)
				.getValue();
		int i = Integer.parseInt(temp);
		return i;
	}
	
	private static Property getProperty(Node node, String key) {
		GraphNode graphNode = node.getGraphNode();
		if (graphNode != null) {
			List list = graphNode.getList(UmaPackage.GRAPH_NODE__PROPERTY);
			if (list != null && !list.isEmpty()) {
				for (int i = list.size() - 1; i > -1; i--) {
					Property prop = (Property) list.get(i);
					if (key.equals(prop.getKey())) {
						return prop;
					}
				}
			}
		}
		return null;
	}
	public void createTaskInputOutputNodes(TaskDescriptor descriptor, Collection nodes) {
		Node newNode = null;
		if (!descriptor.getMandatoryInput().isEmpty()) {
			newNode = createWorkProductComposite(descriptor,
					WorkProductComposite.INPUTS);
			nodes.add(newNode);
		}
		if (!descriptor.getOutput().isEmpty()) {
			newNode = createWorkProductComposite(descriptor,
					WorkProductComposite.OUTPUTS);
			nodes.add(newNode);
		}
	}
	
	public WorkProductComposite createWorkProductComposite(
			TaskDescriptor taskDescriptor, int type) {
		WorkProductComposite workproductComposite = ModelFactory.eINSTANCE
				.createWorkProductComposite();
		workproductComposite.setUMAContainer(getGraphNode());
		workproductComposite.setDiagram(getDiagram());
		workproductComposite.setType(type);
		workproductComposite.setObject(taskDescriptor);
		return workproductComposite;
	}
	
	public void populateNodes(Object newObject){
		
		if (newObject instanceof RoleDescriptor) {
			RoleDescriptor roleDescriptor = (RoleDescriptor) newObject;
			ActivityDetailDiagramImpl diagram = (ActivityDetailDiagramImpl) getDiagram();
			Collection allElements = diagram.getAllBreakdownElements();
			List primaryTaskDescriptors = AssociationHelper.getPrimaryTaskDescriptors(roleDescriptor);
			if (!primaryTaskDescriptors.isEmpty()) { // overriding
																	
				List taskDescriptors = new ArrayList();
				taskDescriptors.addAll(primaryTaskDescriptors);
				HashSet selectedDescriptors = new HashSet();
				List taskNodes = new ArrayList();
				
				String autolayout = GraphicalDataHelper
						.getAutoLayoutFlag((ActivityDetailDiagram) getDiagram()); 
				if(autolayout != null){
					
					int index = 0;
					int rowTasksCount = 0;
					int startCount = 0;
					
					for (Iterator iter = allElements.iterator(); iter.hasNext();) {
						Object obj = iter.next();
						obj = TngUtil.unwrap(obj);
						if (obj instanceof TaskDescriptor
								&& TngUtil.contains(taskDescriptors, obj)) {
							TaskDescriptor taskDescriptor = (TaskDescriptor) obj;
							
							if(startCount < rowIndex * GraphicalDataHelper.getTasksPerRow()){
								startCount++;
							} else {

								if (!selectedDescriptors
										.contains(taskDescriptor)) {
									selectedDescriptors.add(taskDescriptor);
									Node node = GraphicalDataHelper.findNode(
											this, taskDescriptor,
											TaskNode.class);
									if (node == null) {
//										node = createTaskNode(taskDescriptor,
//												index, allElements);
										node = ModelFactory.eINSTANCE.createTaskNode();
										node.setDiagram(getDiagram());
										node.setObject(taskDescriptor);
										((NamedNodeImpl) node).setItemProvider(allElements);
										if (GraphicalDataHelper.findProperty(node.getGraphNode(),
												GraphicalDataHelper.PROP_INDEX) == null
												|| GraphicalDataHelper
														.isAutoLayout((ActivityDetailDiagram) getDiagram())) {
											GraphicalDataHelper.createProperty(node.getGraphNode(),
													GraphicalDataHelper.PROP_INDEX, new Integer(index)
															.toString());
											index++;
										}
										//return node;
									}
									if (node != null) {
										if (rowTasksCount < GraphicalDataHelper
												.getTasksPerRow()) {
											taskNodes.add(node);
											rowTasksCount++;
										} else {
											break;
										}
									}
								}
							}
						}
					}
					// Sort the taskNode based on their index if autolayout is
					// false
					if (GraphicalDataHelper.PROP_AUTO_LAYOUT_VALUE_FALSE
							.equals(autolayout)) {
						Collections.sort(taskNodes, comparator);
					}
			  }else{
					// Lame way of doing this, to fix a defect of 1.0 to 1.0.1 migration
				  	List graphNodes = getUMADiagram().getContained();
				  	List oldTaskDescriptors = new ArrayList();
				  	for (Iterator iter = graphNodes.iterator(); iter.hasNext();) {
				  		GraphNode element = (GraphNode) iter.next();
				  		Object bridge = element.getSemanticModel();
				  		if(bridge instanceof UMASemanticModelBridge){
				  			Object taskObject = ((UMASemanticModelBridge)bridge).getElement();
				  			List list = element.getList(UmaPackage.GRAPH_NODE__PROPERTY);
							Property property = GraphicalDataHelper.getPropertyByKey(list,
									GraphicalDataHelper.PROP_WORK_PRODUCT_COMPOSITE_TYPE);
				  			if (taskDescriptors.contains(taskObject) && property == null) {
				  				oldTaskDescriptors.add(taskObject);
				  			}
				  		}
					}
				  	
					for (Iterator iter = oldTaskDescriptors.iterator(); iter.hasNext();) {
						TaskDescriptor taskDescriptor = (TaskDescriptor) iter.next();
						
						// eliminate descriptor that is duplicate, suppressed or filtered out
						//
						if(!selectedDescriptors.contains(taskDescriptor)
								&& contains(allElements, taskDescriptor) // make sure that task descriptor is of the owning activity
						) {
							selectedDescriptors.add(taskDescriptor);					
						Node node = GraphicalDataHelper.findNode(getDiagram(),
									taskDescriptor, TaskNode.class);
						if (node == null) {
							node = ModelFactory.eINSTANCE.createTaskNode();
							node.setDiagram(getDiagram());
							node.setObject(taskDescriptor);
							((NamedNodeImpl) node).setItemProvider(allElements);
						}
						taskNodes.add(node);
						}
					}
				}
				if(!taskNodes.isEmpty()) {
					// add role node
					//
					Node node = (NamedNodeImpl) ModelFactory.eINSTANCE.createRoleNode();
					node.setDiagram(getDiagram());
					node.setObject(roleDescriptor);
					((NamedNodeImpl) node).setItemProvider(allElements);
					getNodes().add(node);
					// add task nodes
					//
					getNodes().addAll(taskNodes);
				}
			}
		}
		
	}
	
//	public Node createTaskNode(TaskDescriptor taskDescriptor, int index, Collection allElements) {
//		Node node = ModelFactory.eINSTANCE.createTaskNode();
//		node.setDiagram(getDiagram());
//		node.setObject(taskDescriptor);
//		((NamedNodeImpl) node).setItemProvider(allElements);
//		if (GraphicalDataHelper.findProperty(node.getGraphNode(),
//				GraphicalDataHelper.PROP_INDEX) == null
//				|| GraphicalDataHelper
//						.isAutoLayout((ActivityDetailDiagram) getDiagram())) {
//			GraphicalDataHelper.createProperty(node.getGraphNode(),
//					GraphicalDataHelper.PROP_INDEX, new Integer(index)
//							.toString());
//			index++;
//		}
//		return node;
//	}
	
	public void setRowIndex(int rowIndex){
		this.rowIndex = rowIndex;
	}
	public int getRowIndex(){
		return rowIndex;
	}
} // RoleTaskCompositeImpl
