//------------------------------------------------------------------------------
// 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.library.edit.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.ui.viewer.IViewerProvider;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.AdapterFactoryTreeIterator;
import org.eclipse.emf.edit.provider.IChangeNotifier;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.emf.edit.provider.IWrapperItemProvider;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.emf.edit.provider.ViewerNotification;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.edit.IConfigurationApplicator;
import org.eclipse.epf.library.edit.IConfigurator;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.Providers;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.process.BSActivityItemProvider;
import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.ComposedBreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.DescribableElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.IBSItemProvider;
import org.eclipse.epf.library.edit.process.RoleDescriptorWrapperItemProvider;
import org.eclipse.epf.library.edit.process.WorkProductDescriptorWrapperItemProvider;
import org.eclipse.epf.library.edit.process.command.BSDropCommand;
import org.eclipse.epf.library.edit.process.command.ProcessCommandUtil;
import org.eclipse.epf.library.edit.process.command.WBSDropCommand;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.validation.NameChecker;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Artifact;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.CompositeRole;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.Deliverable;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.Guidance;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.TeamProfile;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.provider.UmaEditPlugin;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.Viewer;

import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.util.StringTokenizer;


/**
 * Utility class that defines static methods for process authoring
 * 
 * @author Phong Nguyen Le
 * @author Shilpa Toraskar
 * @since 1.0
 */
public final class ProcessUtil {
	private static Collection OBSEclasses = null;

	private static Collection WBSEclasses = null;

	private static Collection PBSEclasses = null;

	private static Collection extendAndLocalContributionVariabilityTypes = null;

	private static Collection getExtendAndLocalContributionVariabilityTypes() {
		if (extendAndLocalContributionVariabilityTypes == null) {
			extendAndLocalContributionVariabilityTypes = new ArrayList();
			extendAndLocalContributionVariabilityTypes
					.add(VariabilityType.EXTENDS_LITERAL);
			extendAndLocalContributionVariabilityTypes
					.add(VariabilityType.LOCAL_CONTRIBUTION_LITERAL);
		}
		return extendAndLocalContributionVariabilityTypes;
	}

	public static String checkBreakdownElementName(
			AdapterFactory adapterFactory, BreakdownElement e, String name, Suppression suppression) {
		return NameChecker.checkName(adapterFactory, e, UmaPackage.eINSTANCE
				.getNamedElement_Name(), name, suppression);
	}
	
	public static String checkBreakdownElementName(
			AdapterFactory adapterFactory, BreakdownElement e, String name, Suppression suppression, boolean ignoreSuppressed) {
		return NameChecker.checkName(adapterFactory, e, UmaPackage.eINSTANCE
				.getNamedElement_Name(), name, suppression, ignoreSuppressed);
	}

	public static String checkBreakdownElementPresentationName(
			AdapterFactory adapterFactory, BreakdownElement e, String name, Suppression suppression) {
		// might allow empty presentation name for extender or contributor. The element will inherit
		// the presentation name from the base element. Check will be performed on the inherited name
		//
		if (name == null || name.length() == 0) {
			if (isExtendingOrLocallyContributing(e)) {
				BreakdownElement base = (BreakdownElement) ((VariabilityElement) e)
						.getVariabilityBasedOnElement();
				name = getPresentationName(base);
			}
		}
		return NameChecker.checkName(adapterFactory, e, UmaPackage.eINSTANCE
				.getDescribableElement_PresentationName(), name, suppression);
	}
	
	public static String checkBreakdownElementPresentationName(
			AdapterFactory adapterFactory, BreakdownElement e, String name, Suppression suppression, boolean ignoreSuppressed) {

		return NameChecker.checkName(adapterFactory, e, UmaPackage.eINSTANCE
				.getDescribableElement_PresentationName(), name, suppression, ignoreSuppressed);
	}

	public static Object getRootProcess(AdapterFactory adapterFactory,
			ItemProviderAdapter adapter, Object obj) {
		Object parent = adapter.getParent(obj);
		adapter = (ItemProviderAdapter) adapterFactory.adapt(parent,
				ITreeItemContentProvider.class);
		if (parent == null) {
			return obj;
		} else {
			return getRootProcess(adapterFactory, adapter, parent);
		}
	}

	public static Collection getWBSEclasses() {
		if (WBSEclasses == null) {
			WBSEclasses = new HashSet();
			WBSEclasses.add(UmaPackage.eINSTANCE.getTaskDescriptor());
			WBSEclasses.add(UmaPackage.eINSTANCE.getActivity());
			WBSEclasses.add(UmaPackage.eINSTANCE.getMilestone());
		}
		return WBSEclasses;
	}

	public static Collection getOBSEclasses() {
		if (OBSEclasses == null) {
			OBSEclasses = new HashSet();
			OBSEclasses.add(UmaPackage.eINSTANCE.getRoleDescriptor());
			OBSEclasses.add(UmaPackage.eINSTANCE.getActivity());
			OBSEclasses.add(UmaPackage.eINSTANCE.getMilestone());
			OBSEclasses.add(UmaPackage.eINSTANCE.getTeamProfile());
			OBSEclasses.add(UmaPackage.eINSTANCE.getCompositeRole());
		}

		return OBSEclasses;
	}

	public static Collection getPBSEclasses() {
		if (PBSEclasses == null) {
			PBSEclasses = new HashSet();
			PBSEclasses.add(UmaPackage.eINSTANCE.getWorkProductDescriptor());
			PBSEclasses.add(UmaPackage.eINSTANCE.getActivity());
			PBSEclasses.add(UmaPackage.eINSTANCE.getMilestone());
		}
		return PBSEclasses;
	}

	public static boolean isFirstElement(AdapterFactory adapterFactory,
			ItemProviderAdapter itemProvider, Object obj) {
		Object parent = itemProvider.getParent(obj);
		if (parent instanceof TeamProfile)
			return true;
		LinkedList siblings = getSiblings(adapterFactory, itemProvider, obj);
		if (siblings != null && !siblings.isEmpty()) {
			return siblings.getFirst() == obj;
		}
		return true;
	}

	public static LinkedList getSiblings(AdapterFactory adapterFactory,
			ItemProviderAdapter itemProvider, Object obj) {
		Object parent = itemProvider.getParent(obj);
		if (parent == null)
			return null;
		ITreeItemContentProvider parentItemProvider = (ITreeItemContentProvider) adapterFactory
				.adapt(parent, ITreeItemContentProvider.class);
		if (parentItemProvider != null) {
			return new LinkedList(parentItemProvider.getChildren(parent));
		}
		return null;
	}

	public static boolean isLastElement(AdapterFactory adapterFactory,
			ItemProviderAdapter itemProvider, Object obj) {
		Object parent = itemProvider.getParent(obj);
		if (parent instanceof TeamProfile)
			return true;
		LinkedList siblings = getSiblings(adapterFactory, itemProvider, obj);
		if (siblings != null && !siblings.isEmpty()) {
			return siblings.getLast() == obj;
		}
		return true;
	}

	/**
	 * Gets elements that have been affected after the event that triggered the
	 * given notification.
	 * 
	 * @param notification
	 * @param filter
	 * @return
	 */
	public static List getAffectedElements(Notification notification,
			IFilter filter) {
		List affectedElements = new ArrayList();
		switch (notification.getEventType()) {
		case Notification.ADD:
			Object obj = notification.getNewValue();
			if (filter == null || filter.accept(obj)) {
				affectedElements.add(obj);
			}
			break;
		case Notification.ADD_MANY:
			for (Iterator iter = ((Collection) notification.getNewValue())
					.iterator(); iter.hasNext();) {
				Object element = iter.next();
				if (filter == null || filter.accept(element)) {
					affectedElements.add(element);
				}
			}
			break;
		case Notification.REMOVE:
			obj = notification.getOldValue();
			if (filter == null || filter.accept(obj)) {
				affectedElements.add(obj);
			}
			break;
		case Notification.REMOVE_MANY:
			for (Iterator iter = ((Collection) notification.getOldValue())
					.iterator(); iter.hasNext();) {
				Object element = iter.next();
				if (filter == null || filter.accept(element)) {
					affectedElements.add(element);
				}
			}
			break;

		case Notification.MOVE:
			obj = notification.getNewValue();
			if (obj instanceof Collection) {
				for (Iterator iter = ((Collection) obj).iterator(); iter
						.hasNext();) {
					Object element = iter.next();
					if (filter == null || filter.accept(element)) {
						affectedElements.add(element);
					}
				}
			} else {
				if (filter == null || filter.accept(obj)) {
					affectedElements.add(obj);
				}
			}
			break;
		}
		return affectedElements;
	}

	public static boolean isRefreshRequired(Notification notification,
			IFilter filter) {
		switch (notification.getEventType()) {
		case Notification.SET:
		case Notification.ADD:
			Object obj = notification.getNewValue();
			if (filter == null || filter.accept(obj)) {
				return true;
			}
			break;
		case Notification.ADD_MANY:
			for (Iterator iter = ((Collection) notification.getNewValue())
					.iterator(); iter.hasNext();) {
				Object element = iter.next();
				if (filter == null || filter.accept(element)) {
					return true;
				}
			}
			break;
		case Notification.REMOVE:
			obj = notification.getOldValue();
			if (filter == null || filter.accept(obj)) {
				return true;
			}
			break;
		case Notification.REMOVE_MANY:
			for (Iterator iter = ((Collection) notification.getOldValue())
					.iterator(); iter.hasNext();) {
				Object element = iter.next();
				if (filter == null || filter.accept(element)) {
					return true;
				}
			}
			break;

		case Notification.MOVE:
			obj = notification.getNewValue();
			if (obj instanceof Collection) {
				for (Iterator iter = ((Collection) obj).iterator(); iter
						.hasNext();) {
					Object element = iter.next();
					if (filter == null || filter.accept(element)) {
						return true;
					}
				}
			} else {
				if (filter == null || filter.accept(obj)) {
					return true;
				}
			}
			break;
		}

		return false;
	}

	public static void addToContainer(BreakdownElement e,
			ItemProviderAdapter itemProvider) {
		addToContainer(e, itemProvider, true);
	}

	/**
	 * Adds the given BreakdownElement to a new container if it does not have
	 * one or moves it to the right container if requested.
	 * 
	 * @param e
	 * @param itemProvider
	 */
	public static void addToContainer(BreakdownElement e,
			ItemProviderAdapter itemProvider, boolean move) {
		ProcessPackage pkg = null;
		Object parent = itemProvider.getParent(e);
		if (parent instanceof EObject) {
			EObject container = ((EObject) parent).eContainer();
			if (container instanceof ProcessPackage) {
				pkg = (ProcessPackage) container;
			}
		}

		if (pkg == null) {
			return;
		}

		if (e instanceof Activity) {
			Activity act = (Activity) e;
			if (act.eContainer() == null) {
				// create new ProcessPackage for the activity
				//
				ProcessPackage newPkg = UmaFactory.eINSTANCE
						.createProcessPackage();
				newPkg.setName(act.getName());
				pkg.getChildPackages().add(newPkg);
				newPkg.getProcessElements().add(e);
			} else if (move) {
				// Check if the activity's ProcessPackage is at the right place.
				// If not, move it to the right ProcessComponent.
				//
				ProcessPackage oldPkg = (ProcessPackage) act.eContainer();
				if (oldPkg.eContainer() != pkg) {
					pkg.getChildPackages().add(oldPkg);
				}
			}
		} else {
			if (e.eContainer() == null) {
				pkg.getProcessElements().add(e);
			} else if (move && e.eContainer() != pkg) {
				// move to new ProcessPackage
				//
				pkg.getProcessElements().add(e);
			}
		}
	}

	public static void setParent(Object child, Object parent,
			AdapterFactory adapterFactory) {
		Object adapter = adapterFactory.adapt(child,
				ITreeItemContentProvider.class);
		if (adapter instanceof IBSItemProvider) {
			((IBSItemProvider) adapter).setParent(parent);
		} 
//		else {
//			System.out
//					.println(LibraryEditResources.util_ProcessUtil_err_setparent + child); //$NON-NLS-1$
//			System.out
//					.println(LibraryEditResources.util_ProcessUtil_childadapter + adapter); //$NON-NLS-1$
//		}
	}

	/**
	 * Creates a new RoleDescriptor from the given role.
	 * 
	 * @param role
	 * @return
	 */
	public static RoleDescriptor createRoleDescriptor(Role role) {
		RoleDescriptor roleDesc = UmaFactory.eINSTANCE.createRoleDescriptor();
		roleDesc.setRole(role);
		String presentationName = role.getPresentationName();
		roleDesc.setName(role.getName());
		roleDesc.setPresentationName(StrUtil.isBlank(presentationName) ? role
				.getName() : presentationName);
		// roleDesc.setBriefDescription(role.getBriefDescription());
		return roleDesc;
	}

	public static WorkProductDescriptor createWorkProductDescriptor(
			WorkProduct wp) {
		WorkProductDescriptor wpDesc = UmaFactory.eINSTANCE
				.createWorkProductDescriptor();
		wpDesc.setWorkProduct(wp);
		wpDesc.setName(wp.getName());
		wpDesc
				.setPresentationName(StrUtil.isBlank(wp.getPresentationName()) ? wp
						.getName()
						: wp.getPresentationName());
		// wpDesc.setBriefDescription(wp.getBriefDescription());
		return wpDesc;
	}

	public static Viewer getViewer(AdapterFactory adapterFactory, Process proc) {
		if (adapterFactory instanceof ExposedAdapterFactory) {
			for (Iterator iter = Collections.unmodifiableList(
					((ExposedAdapterFactory) adapterFactory)
							.getChangeListeners()).iterator(); iter.hasNext();) {
				Object listener = iter.next();
				if (listener instanceof IContentProvider && listener instanceof IViewerProvider) {					
					Viewer viewer = ((IViewerProvider) listener).getViewer();
					if (viewer.getInput() instanceof ProcessComponent
							&& ((ProcessComponent) viewer.getInput())
									.getProcess() == proc)
						return viewer;
				}
			}
		}
		return null;
	}

	public static boolean refreshNeeded(AdapterFactory adapterFactory,
			BSActivityItemProvider itemProvider) {
		Process process = (Process) itemProvider.getTopItem();
		if (process == null)
			return false;

		// check if the given process is currently opened in editor
		//
		Viewer viewer = getViewer(adapterFactory, process);
		if (viewer != null && viewer.getControl() != null
				&& !viewer.getControl().isDisposed()) {
			return true;
		}

		for (Iterator iter = TngUtil.getContributors(process); iter.hasNext();) {
			Object element = iter.next();
			BSActivityItemProvider adapter = (BSActivityItemProvider) adapterFactory
					.adapt(element, ITreeItemContentProvider.class);
			if (refreshNeeded(adapterFactory, adapter))
				return true;
		}

		for (Iterator iter = TngUtil.getGeneralizers(process,
				VariabilityType.EXTENDS_LITERAL); iter.hasNext();) {
			Object element = iter.next();
			BSActivityItemProvider adapter = (BSActivityItemProvider) adapterFactory
					.adapt(element, ITreeItemContentProvider.class);
			if (refreshNeeded(adapterFactory, adapter))
				return true;
		}

		return false;
	}
	
	public static void refreshPredeccessorLists(AdapterFactory factory, Process proc) {
		Object obj;
		Object element;
		for (Iterator iter = new AdapterFactoryTreeIterator(factory, proc); iter
		.hasNext();) {
			obj = iter.next();
			element = TngUtil.unwrap(obj);
			if(element instanceof WorkBreakdownElement) {
				Object adapter = factory.adapt(obj, ITreeItemContentProvider.class);
				if (adapter instanceof IBSItemProvider) {				
					IBSItemProvider itemProvider = (IBSItemProvider) adapter;
					PredecessorList predList = itemProvider.getPredecessors();
					if(predList != null) {
						predList.refresh();
					}
				}
			}
		}
	}
	
	/**
	 * Updates IDs of work breakdown elements of the view of the given process
	 * 
	 * @param factory
	 *            adapter factory of the current process view (WBS, TBS, WPBS,
	 *            CBS)
	 * @param proc
	 *            must be refreshed.
	 */
	public static void updateIDs(AdapterFactory factory, Process proc) {
		int id = 0;
		Object obj;
		// Map changeMap = new HashMap();
		for (Iterator iter = new AdapterFactoryTreeIterator(factory, proc); iter
				.hasNext();) {
			obj = iter.next();
			Object adapter = factory.adapt(obj, ITreeItemContentProvider.class);
			if (adapter instanceof IBSItemProvider) {
				IBSItemProvider itemProvider = (IBSItemProvider) adapter;
				if (itemProvider != null
						&& TngUtil.unwrap(obj) instanceof WorkBreakdownElement) {
					itemProvider.setId(id++);
					// changeMap.put(obj, itemProvider);
				}
			}
		}

		// refresh the label
		//
		// for (Iterator iterator = changeMap.entrySet().iterator();
		// iterator.hasNext();) {
		// Map.Entry entry = (Map.Entry) iterator.next();
		// IChangeNotifier adapter = (IChangeNotifier) entry.getValue();
		// obj = entry.getKey();
		// adapter.fireNotifyChanged(new ViewerNotification(new
		// NotificationImpl(Notification.SET, obj, obj), obj, false, true));
		// }
	}

	public static void refreshViewer(AdapterFactory factory, Process proc) {
		final Viewer viewer = getViewer(factory, proc);
		if (viewer != null && viewer.getControl() != null
				&& !viewer.getControl().isDisposed()) {
			UserInteractionHelper.runInUIThread(new Runnable() {

				public void run() {
					viewer.refresh();
				}
				
			});
		}
	}

	/**
	 * Refreshes the element IDs in those viewers that require this.
	 * 
	 * @param adapterFactory
	 */
	public static void refreshIDsInViewers(final ExposedAdapterFactory adapterFactory) {
		UserInteractionHelper.runInUIThread(new Runnable() {

			public void run() {
				for (Iterator iter = Collections.unmodifiableList(
						adapterFactory.getChangeListeners()).iterator(); iter.hasNext();) {
					Object listener = iter.next();
					if (listener instanceof IContentProvider && listener instanceof IViewerProvider) {					
						Viewer viewer = ((IViewerProvider) listener).getViewer();
						if (viewer != null && viewer.getControl() != null
								&& !viewer.getControl().isDisposed()
								&& viewer.getInput() instanceof ProcessComponent) {
							Process proc = ((ProcessComponent) viewer.getInput())
									.getProcess();
							BSActivityItemProvider itemProvider = (BSActivityItemProvider) adapterFactory
									.adapt(proc, ITreeItemContentProvider.class);
							if (itemProvider.isRefreshAllIDsRequired()) {
								updateIDs(adapterFactory, proc);
								viewer.refresh();
								itemProvider.setRefreshAllIDsRequired(false);
							}
						}
					}
				}
			}
			
		});
	}

	public static void refreshAllViewers(final ExposedAdapterFactory adapterFactory) {
		UserInteractionHelper.runInUIThread(new Runnable() {

			public void run() {
				for (Iterator iter = Collections.unmodifiableList(
						adapterFactory.getChangeListeners()).iterator(); iter.hasNext();) {
					Object listener = iter.next();
					if (listener instanceof IContentProvider && listener instanceof IViewerProvider) {					
						Viewer viewer = ((IViewerProvider) listener).getViewer();
						if (viewer != null && viewer.getControl() != null
								&& !viewer.getControl().isDisposed()
								&& viewer.getInput() instanceof ProcessComponent) {
							viewer.refresh();
						}
					}
				}
			}
			
		});
	}
	
	/**
	 * @param e
	 *            the breakdown element whose predecessor list to be checked.
	 * @param predIdList
	 *            a list of predecessor IDs (Integer) as shown in the ID column
	 *            of the editor
	 * @param adapterFactory
	 * @param process
	 * @param predecessors
	 *            output, the predecessor list
	 * @return null if predList is valid, an error message otherwise
	 */
	public static String checkPredecessorList(WorkBreakdownElement e,
			List predIdList, AdapterFactory adapterFactory, Object process,
			List predecessors) {
		// get BreakdownElement list from ID list
		//
		List beList = new ArrayList();
		List allElements = new ArrayList();
		for (Iterator iter = new AdapterFactoryTreeIterator(adapterFactory,
				process); iter.hasNext();) {
			Object obj = iter.next();
			IBSItemProvider itemProvider = (IBSItemProvider) adapterFactory
					.adapt(obj, ITreeItemContentProvider.class);
			Integer id = new Integer(itemProvider.getId());
			obj = TngUtil.unwrap(obj);
			allElements.add(obj);
			if (predIdList.contains(id)) {
				beList.add(obj);
			}
		}

		// check for circular dependency
		//
		int size = beList.size();
		for (int i = 0; i < size; i++) {
			Object obj = beList.get(i);
			if (obj instanceof WorkBreakdownElement) {
				WorkBreakdownElement pred = (WorkBreakdownElement) obj;
				if (ProcessUtil.checkCircular(e, pred, allElements)) {
					return LibraryEditResources.util_ProcessUtil_err_same_breakdown_element; //$NON-NLS-1$
				}
				if (TngUtil.isSubelementOf(pred, e, adapterFactory)) {
					return LibraryEditResources.util_ProcessUtil_err_same_sub_element; //$NON-NLS-1$
				}
				if (TngUtil.isSuperElementOf(pred, e, adapterFactory)) {
					return LibraryEditResources.util_ProcessUtil_err_child_element; //$NON-NLS-1$
				}
			} else
				return LibraryEditResources.util_ProcessUtil_err_wrong_element; //$NON-NLS-1$
		}

		if (predecessors != null)
			predecessors.addAll(beList);
		return null;
	}

	/**
	 * Checks for circular dependency
	 * 
	 * @param successor
	 * @param predecessor
	 * @param list
	 *            the list of all breakdown elements in the breakdown structure
	 */
	// public static boolean checkCircular(WorkBreakdownElement successor,
	// WorkBreakdownElement predecessor, List list) {
	// if(successor == predecessor) {
	// if(predecessor.getIsRepeatable().booleanValue()) {
	// return false;
	// }
	// return true;
	// }
	// for (Iterator iter = predecessor.getLinkToPredecessor().iterator();
	// iter.hasNext();) {
	// WorkOrder element = (WorkOrder) iter.next();
	// WorkBreakdownElement pred = element.getPred();
	// if(pred != predecessor && list.contains(pred)) {
	// if(checkCircular(successor, pred, list)) return true;
	// }
	// }
	// return false;
	// }
	public static boolean checkCircular(WorkBreakdownElement successor,
			WorkBreakdownElement predecessor, List list) {
		// if(successor == predecessor) {
		// if(predecessor.getIsRepeatable().booleanValue()) {
		// return false; // if ok return false means allowed.
		// }
		// return true;
		// }
		// List predecessorsList = new ArrayList();
		// getAllPredecessorList(predecessor, list, predecessorsList);
		// if(!predecessorsList.isEmpty()){
		// for(Iterator itor = predecessorsList.iterator(); itor.hasNext();){
		// Object obj = itor.next();
		// if(successor == obj){
		// if(((WorkBreakdownElement)obj).getIsRepeatable().booleanValue())
		// {
		// return false;
		// }
		// return true;
		// }
		// }
		// }
		return false;
	}

	public static void getAllPredecessorList(WorkBreakdownElement predecessor,
			List list, List predList) {
		if (!predList.contains(predecessor))
			predList.add(predecessor);
		for (Iterator iter = predecessor.getLinkToPredecessor().iterator(); iter
				.hasNext();) {
			WorkOrder element = (WorkOrder) iter.next();
			WorkBreakdownElement pred = (WorkBreakdownElement) element
					.getPred();
			if (pred != predecessor && list.contains(pred)) {
				if (!predList.contains(pred)) {
					predList.add(pred);
					getAllPredecessorList(pred, list, predList);
				}
			}
		}
	}

	/**
	 * 
	 * @param e
	 *            the breakdown element whose predecessor list to be checked.
	 * @param predList
	 *            a comma-separated list of predecessor IDs
	 * @param adapterFactory
	 * @param topAct
	 * @param predecessors
	 *            output, the predecessor list
	 * @param allElements
	 *            output, the whole breakdown element list is copied into this
	 *            list.
	 * @return null if predList is valid. The predecessor list is saved in
	 *         predecessors and the whole breakdown element list is saved in
	 *         allElements.
	 */
	public static String checkPredecessorList(WorkBreakdownElement e,
			String predList, AdapterFactory adapterFactory, Object topAct,
			List predecessors) {
		List idList = new ArrayList();
		for (StringTokenizer tokens = new StringTokenizer(predList, ","); tokens.hasMoreTokens();) { //$NON-NLS-1$
			String token = tokens.nextToken().trim();
			Integer id;
			try {
				id = new Integer(token);
			} catch (NumberFormatException ex) {
				return LibraryEditResources.invalidPredecessorError_msg; //$NON-NLS-1$
			}
			idList.add(id);
		}

		return checkPredecessorList(e, idList, adapterFactory, topAct,
				predecessors);
	}

	/**
	 * Adds the given object's method package and plugin to the default
	 * configuration of the given process if they are not in the configuration
	 * yet.
	 * 
	 * @param proc
	 * @param object
	 * @param addedObjects
	 */
	public static void addToDefaultConfiguration(Process proc, EObject e,
			Set addedObjects) {
		// add the element's method package to the default configuration
		//
		MethodConfiguration config = proc.getDefaultContext();
		if (e instanceof Task) {
			addTaskToDefaultConfiguration(proc, (Task) e, addedObjects, true);
		} else if (e instanceof WorkProduct) {
			WorkProduct wp = (WorkProduct) e;
			addWPToDefaultConfiguration(proc, wp, addedObjects);
			List tasks = getTasksForWorkProduct(wp, config);
			if (tasks != null)
			{
				for (Iterator iter = tasks.iterator(); iter.hasNext();) {
					addTaskToDefaultConfiguration(proc, (Task) iter.next(),
							addedObjects, false);
				}
			}
		} else if (e instanceof Role) {
			Role role = (Role) e;
			addRoleToDefaultConfiguration(proc, role, addedObjects);

		} else if (e instanceof Activity) {
			addActivityToDefaultConfiguration(proc, (Activity) e, addedObjects);
		} else if (e instanceof Guidance) {
			TngUtil.addToConfiguration(config, (Guidance) e, addedObjects);
		}
	}
	
	private static void addActivityToDefaultConfiguration(Process proc, Activity activity, Set addedObjects) {
		MethodConfiguration config = proc.getDefaultContext();
		TngUtil.addTo(config, UmaUtil.getProcessComponent(activity), addedObjects);
		// add linked element of descriptors
		//
		for (Iterator iter = activity.getBreakdownElements().iterator(); iter.hasNext();) {
			Object e = (Object) iter.next();
			if(e instanceof Descriptor) {
				MethodElement o = ProcessUtil.getAssociatedElement((Descriptor) e);
				if(o != null) {
					addToDefaultConfiguration(proc, o, addedObjects);
				}
			}
			else if (e instanceof Activity){
				// this is needed for adding sub-activities descriptors 
				addActivityToDefaultConfiguration(proc, (Activity) e, addedObjects);
			}
		}

		// add all the base elements if there is any
		for (Activity base = (Activity) activity.getVariabilityBasedOnElement(); base != null; base = (Activity) base
		.getVariabilityBasedOnElement()) {
			addActivityToDefaultConfiguration(proc, base, addedObjects);
		}
	}

	private static void addTaskToDefaultConfiguration(Process proc, Task task,
			Set addedObjects, boolean includeWorkProducts) {
		MethodConfiguration config = proc.getDefaultContext();

		TngUtil.addToConfiguration(config, task, addedObjects);

		// add all other dependencies
		//

		// add roles
		ArrayList dependencies = new ArrayList();
		dependencies.addAll(task.getAdditionallyPerformedBy());
		dependencies.add(task.getPerformedBy());
		for (Iterator iter = dependencies.iterator(); iter.hasNext();) {
			TngUtil.addToConfiguration(config, (EObject) iter.next(),
					addedObjects);
		}

		// add work products
		if (includeWorkProducts) {
			dependencies.clear();
			dependencies.addAll(task.getOptionalInput());
			dependencies.addAll(task.getOutput());
			dependencies.addAll(task.getMandatoryInput());
			for (Iterator iter = dependencies.iterator(); iter.hasNext();) {
				addWPToDefaultConfiguration(proc, (WorkProduct) iter.next(),
						addedObjects);
			}
		}

		for (Iterator iter = task.getSteps().iterator(); iter.hasNext();) {
			VariabilityElement step = (VariabilityElement) iter.next();
			EObject base = step.getVariabilityBasedOnElement();
			if (base != null) {
				TngUtil.addToConfiguration(config, base, addedObjects);
			}
		}

	}

	private static void addRoleToDefaultConfiguration(Process proc,
			Role role, Set addedObjects) {
		MethodConfiguration config = proc.getDefaultContext();
		TngUtil.addToConfiguration(config, role, addedObjects);
		
		// add work products
		ArrayList dependencies = new ArrayList();
	
		dependencies.addAll(role.getModifies());
		dependencies.addAll(role.getResponsibleFor());
		for (Iterator iter = dependencies.iterator(); iter.hasNext();) {
			addWPToDefaultConfiguration(proc, (WorkProduct) iter.next(),
					addedObjects);
		}
	}
	
	private static void addWPToDefaultConfiguration(Process proc,
			WorkProduct wp, Set addedObjects) {
		MethodConfiguration config = proc.getDefaultContext();
		TngUtil.addToConfiguration(config, wp, addedObjects);
		if (wp instanceof Deliverable) {
			for (Iterator iter = ((Deliverable) wp).getDeliveredWorkProducts()
					.iterator(); iter.hasNext();) {
				TngUtil.addToConfiguration(config, (EObject) iter.next(),
						addedObjects);
			}
		}
	}

	public static void updateTaskDescriptorSteps(Activity activity,
			TaskDescriptor taskDesc) {
		if (taskDesc == null) {
			return;
		}

		Task task = taskDesc.getTask();

		IConfigurationApplicator configApplicator = Providers
				.getConfigurationApplicator();
		MethodConfiguration config = TngUtil.getOwningProcess(activity)
				.getDefaultContext();
		List steps = (List) configApplicator.getReference(task,
				UmaPackage.eINSTANCE.getTask_Steps(), config);

		// add those steps to TaskDescriptor if they are not there yet.
		//
		for (Iterator iter = steps.iterator(); iter.hasNext();) {
			Object step = iter.next();
			if (!taskDesc.getSelectedSteps().contains(step)) {
				taskDesc.getSelectedSteps().add(step);
			}
		}
	}

	/**
	 * Gets the MethodElement that the given descriptor is associated with.
	 * 
	 * @param descriptor
	 * @return
	 */
	public static MethodElement getAssociatedElement(Descriptor descriptor) {
		if (descriptor instanceof RoleDescriptor) {
			return ((RoleDescriptor) descriptor).getRole();
		} else if (descriptor instanceof TaskDescriptor) {
			return ((TaskDescriptor) descriptor).getTask();
		} else if (descriptor instanceof WorkProductDescriptor) {
			return ((WorkProductDescriptor) descriptor).getWorkProduct();
		}
		return null;
	}

	public static void disposeWrappers(Collection children) {
		if (children == null)
			return;
		for (Iterator iter = children.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof IWrapperItemProvider) {
				((IWrapperItemProvider) element).dispose();
			}
		}
	}

	/**
	 * Get all tasks that have the given workproduct in their output
	 * in the given configuration
	 * 
	 * @param wp
	 * @param config
	 * @return
	 */
	public static List getTasksForWorkProduct(WorkProduct wp,
			MethodConfiguration config) {
		IConfigurationApplicator configApplicator = Providers.getConfigurationApplicator();

		List tasks = (List) configApplicator.getReference(wp, AssociationHelper.WorkProduct_OutputFrom_Tasks, config);

		return tasks;
	}

	/**
	 * Get all workproducts that have the role as responsible role in the
	 * given configuration
	 * 
	 * @param wp
	 * @param config
	 * @return
	 */
	public static List getWorkProductsForRole(Role role,
			MethodConfiguration config) {
		IConfigurationApplicator configApplicator = Providers.getConfigurationApplicator();
		List wps = (List) configApplicator.getReference(role, UmaPackage.eINSTANCE.getRole_ResponsibleFor(), config);
		return wps;
	}

	/**
	 * Gets all workproducts which are, except the contributor, in the given
	 * plugin.
	 * 
	 * @param plugin
	 * @return
	 */
	public static List getAllWorkProducts(MethodPlugin plugin) {

		ContentPackage coreContentPkg = UmaUtil.findContentPackage(plugin,
				ModelStructure.DEFAULT.coreContentPath);
		Iterator iter = new AbstractTreeIterator(coreContentPkg, false) {

			/**
			 * Comment for <code>serialVersionUID</code>
			 */
			private static final long serialVersionUID = 3833752066324837937L;

			protected Iterator getChildren(Object object) {
				if (!(object instanceof ContentPackage))
					return Collections.EMPTY_LIST.iterator();
				ContentPackage pkg = (ContentPackage) object;
				List children = new ArrayList();
				for (Iterator iterator = pkg.getChildPackages().iterator(); iterator
						.hasNext();) {
					Object element = iterator.next();
					if (element instanceof ContentPackage) {
						children.add(element);
					}
				}
				for (Iterator iterator = pkg.getContentElements().iterator(); iterator
						.hasNext();) {
					Object element = iterator.next();

					if ((element instanceof WorkProduct)
							&& !TngUtil
									.isContributor((VariabilityElement) element)) {
						children.add(element);
					}
				}
				return children.iterator();
			}

		};
		List methodElements = new ArrayList();
		while (iter.hasNext()) {
			Object e = iter.next();
			if (e instanceof WorkProduct) {
				methodElements.add(e);
			}
		}
		return methodElements;
	}

	/**
	 * Gets all task, except the contributor, in the given plugin.
	 * 
	 * @param plugin
	 * @return
	 */
	public static List getAllTasks(MethodPlugin plugin) {
		ContentPackage coreContentPkg = UmaUtil.findContentPackage(plugin,
				ModelStructure.DEFAULT.coreContentPath);
		Iterator iter = new AbstractTreeIterator(coreContentPkg, false) {

			/**
			 * Comment for <code>serialVersionUID</code>
			 */
			private static final long serialVersionUID = 3833752066324837937L;

			protected Iterator getChildren(Object object) {
				if (!(object instanceof ContentPackage))
					return Collections.EMPTY_LIST.iterator();
				ContentPackage pkg = (ContentPackage) object;
				List children = new ArrayList();
				for (Iterator iterator = pkg.getChildPackages().iterator(); iterator
						.hasNext();) {
					Object element = iterator.next();
					if (element instanceof ContentPackage) {
						children.add(element);
					}
				}
				for (Iterator iterator = pkg.getContentElements().iterator(); iterator
						.hasNext();) {
					Object element = iterator.next();
					if (element instanceof Task
							&& !TngUtil
									.isContributor((VariabilityElement) element)) {
						children.add(element);
					}
				}
				return children.iterator();
			}

		};
		List tasks = new ArrayList();
		while (iter.hasNext()) {
			Object e = iter.next();
			if (e instanceof Task) {
				tasks.add(e);
			}
		}
		return tasks;
	}

	public static boolean isExtendingOrLocallyContributing(BreakdownElement e) {
		return TngUtil.isGeneralizer(e,
				getExtendAndLocalContributionVariabilityTypes());
	}
	

	public static String getPresentationName(BreakdownElement e) {
		if (e.getPresentationName() == null
				|| e.getPresentationName().length() == 0) {
			if (isExtendingOrLocallyContributing(e)) {
				BreakdownElement base = (BreakdownElement) ((VariabilityElement) e)
						.getVariabilityBasedOnElement();
				return getPresentationName(base);
			}
		}

		return e.getPresentationName();
	}

	public static String getLabelWithPath(BreakdownElement e) {
		StringBuffer path = new StringBuffer(e.getName());
		Process proc = TngUtil.getOwningProcess(e);
		if (proc != null) {
			path.append(", "); //$NON-NLS-1$
			MethodPlugin plugin = UmaUtil.getMethodPlugin(proc);
			if (plugin != null) {
				path.append(plugin.getName());
			}
			if (e != proc) {
				path.append('/').append(proc.getName());
			}
		}
		return path.toString();
	}

	/**
	 * Gets the model info of the given BreakdownElement in the given
	 * StringBuffer
	 * 
	 * @param e
	 * @param adapter
	 * @param modelInfo
	 */
	public static void getModelInfo(BreakdownElement e, Object adapter,
			StringBuffer modelInfo) {
		if (e instanceof VariabilityElement) {
			VariabilityElement ve = (VariabilityElement) e;
			VariabilityElement base = ve.getVariabilityBasedOnElement();
			if (base != null) {
				VariabilityType type = ve.getVariabilityType();
				if (modelInfo.length() > 0) {
					modelInfo.append("; "); //$NON-NLS-1$
				}
				String pattern = null;
				if (type == VariabilityType.CONTRIBUTES_LITERAL) {
					pattern = LibraryEditResources.util_ProcessUtil_contributesto; //$NON-NLS-1$
				} else if (type == VariabilityType.LOCAL_CONTRIBUTION_LITERAL) {
					pattern = LibraryEditResources.util_ProcessUtil_localContributesto; //$NON-NLS-1$
				} else if (type == VariabilityType.EXTENDS_LITERAL) {
					pattern = LibraryEditResources.process_extends; //$NON-NLS-1$
				} else if (type == VariabilityType.REPLACES_LITERAL) {
					pattern = LibraryEditResources.process_replaces; //$NON-NLS-1$
				} else if (type == VariabilityType.LOCAL_REPLACEMENT_LITERAL) {
					pattern = LibraryEditResources.process_localReplaces; //$NON-NLS-1$
				}

				// if(adapter instanceof ItemProviderAdapter) {
				// AdapterFactory factory =
				// ((ItemProviderAdapter)adapter).getAdapterFactory();
				// Object itemProvider = factory.adapt(base,
				// ITreeItemContentProvider.class);
				// if(itemProvider instanceof IBSItemProvider) {
				// IBSItemProvider bsItemProvider = (IBSItemProvider)
				// itemProvider;
				// Process proc = (Process) bsItemProvider.getTopItem();
				// if(proc != null) {
				// strbuf.append(UmaUtil.getMethodPlugin(proc).getName()).append(':')
				// .append(proc.getName()).append(':');
				// }
				// }
				// }

				// Process proc = TngUtil.getOwningProcess((BreakdownElement)
				// base);
				// if(proc != null) {
				// MethodPlugin plugin = UmaUtil.getMethodPlugin(proc);
				// if(plugin != null) {
				// modelInfo.append(UmaUtil.getMethodPlugin(proc).getName()).append(':');
				// }
				// modelInfo.append(proc.getName());
				// }
				//				
				// if(base != proc) {
				// modelInfo.append(':').append(base.getName());
				// }
				// modelInfo.append("'"); //$NON-NLS-1$
				if (pattern != null) {
					String path = getLabelWithPath((BreakdownElement) base);
					modelInfo.append(MessageFormat.format(pattern,
							new Object[] { path }));

					getModelInfo((BreakdownElement) base, adapter, modelInfo);
				}
			}
		} else if (adapter instanceof BreakdownElementWrapperItemProvider) {
			BreakdownElementWrapperItemProvider wrapper = (BreakdownElementWrapperItemProvider) adapter;
			wrapper.getOwner();
			if (wrapper.getFeature() != null) {
				modelInfo.append(TngUtil.getFeatureText(wrapper.getFeature()));
			} else {
				if (wrapper instanceof WorkProductDescriptorWrapperItemProvider) {
//					getModelInfoForWorkProductDescriptor(modelInfo,
//							(WorkProductDescriptor) TngUtil.unwrap(wrapper));
					getWPDModelInfo(modelInfo, wrapper, wrapper);
				}
			}
		}
	}
	
	public static String getColumnName(String property) {
		if (IBSItemProvider.COL_ID.equals(property)) {
			return IBSItemProvider.COL_ID;
		} else if (IBSItemProvider.COL_NAME.equals(property)) {
			return IBSItemProvider.COL_NAME;
		} else if (IBSItemProvider.COL_PRESENTATION_NAME.equals(property)) {
			return IBSItemProvider.COL_PRESENTATION_NAME;
		} else if (IBSItemProvider.COL_PREDECESSORS.equals(property)) {
			return IBSItemProvider.COL_PREDECESSORS;
		} else if (IBSItemProvider.COL_IS_EVENT_DRIVEN.equals(property)) {
			return IBSItemProvider.COL_IS_EVENT_DRIVEN;
		} else if (IBSItemProvider.COL_IS_ONGOING.equals(property)) {
			return IBSItemProvider.COL_IS_ONGOING;
		} else if (IBSItemProvider.COL_IS_REPEATABLE.equals(property)) {
			return IBSItemProvider.COL_IS_REPEATABLE;
		} else if (IBSItemProvider.COL_PREFIX.equals(property)) {
			return IBSItemProvider.COL_PREFIX;
		} else if (IBSItemProvider.COL_MODEL_INFO.equals(property)) {
			return IBSItemProvider.COL_MODEL_INFO;
		} else if (IBSItemProvider.COL_TYPE.equals(property)) {
			return IBSItemProvider.COL_TYPE;
		} else if (IBSItemProvider.COL_TEAMS.equals(property)) {
			return IBSItemProvider.COL_TEAMS;
		} else if (IBSItemProvider.COL_ENTRY_STATE.equals(property)) {
			return IBSItemProvider.COL_ENTRY_STATE;
		} else if (IBSItemProvider.COL_EXIT_STATE.equals(property)) {
			return IBSItemProvider.COL_EXIT_STATE;
		} else if (IBSItemProvider.COL_DELIVERABLE.equals(property)) {
			return IBSItemProvider.COL_DELIVERABLE;
		} else if (IBSItemProvider.COL_IS_OPTIONAL.equals(property)) {
			return IBSItemProvider.COL_IS_OPTIONAL;
		} else if (IBSItemProvider.COL_IS_PLANNED.equals(property)) {
			return IBSItemProvider.COL_IS_PLANNED;
		} else if (IBSItemProvider.COL_HAS_MULTIPLE_OCCURRENCES.equals(property)) {
			return IBSItemProvider.COL_HAS_MULTIPLE_OCCURRENCES;
		}
		return null;
	}

	public static String getAttribute(Object object, String property,
			Object adapter) {
		BreakdownElement e = (BreakdownElement) TngUtil.unwrap(object);
		if (property == IBSItemProvider.COL_ID) {
			if (e instanceof WorkBreakdownElement
					&& adapter instanceof IBSItemProvider) {
				return String.valueOf(((IBSItemProvider) adapter).getId());
			}
		} else if (property == IBSItemProvider.COL_NAME) {
			if (adapter instanceof IItemLabelProvider) {
				return ((IItemLabelProvider) adapter).getText(e);
			}
		} else if (property == IBSItemProvider.COL_PRESENTATION_NAME) {
			return getPresentationName(e);
		} else if (property == IBSItemProvider.COL_PREDECESSORS) {
			if (adapter instanceof IBSItemProvider) {
				return ((IBSItemProvider) adapter).getPredecessors().toString();
			}
		} else if (property == IBSItemProvider.COL_IS_EVENT_DRIVEN) {
			if (e instanceof WorkBreakdownElement) {
				return String.valueOf(((WorkBreakdownElement) e)
						.getIsEventDriven());
			}
		} else if (property == IBSItemProvider.COL_IS_ONGOING) {
			if (e instanceof WorkBreakdownElement) {
				return String
						.valueOf(((WorkBreakdownElement) e).getIsOngoing());
			}
		} else if (property == IBSItemProvider.COL_IS_REPEATABLE) {
			if (e instanceof WorkBreakdownElement) {
				return String.valueOf(((WorkBreakdownElement) e)
						.getIsRepeatable());
			}
		} else if (property == IBSItemProvider.COL_PREFIX) {
			return e.getPrefix();
		} else if (property == IBSItemProvider.COL_MODEL_INFO) {
			StringBuffer modelInfo = new StringBuffer();
			getModelInfo(e, adapter, modelInfo);
			return modelInfo.toString();
		} else if (property == IBSItemProvider.COL_TYPE) {
			String typeName = null;
			if (e instanceof WorkProductDescriptor) {
				WorkProduct wp = ((WorkProductDescriptor) e)
						.getWorkProduct();
				if (wp != null) {
					typeName = wp.eClass().getName() + "Descriptor"; //$NON-NLS-1$  
				}
			}
			if (typeName == null && e instanceof EObject) {
				typeName = ((EObject) e).eClass().getName();
			}
			if (typeName != null) {
				return UmaEditPlugin.INSTANCE
						.getString("_UI_" + typeName + "_type"); //$NON-NLS-1$ //$NON-NLS-2$
			}
		} else if (property == IBSItemProvider.COL_TEAMS) {
			if (e instanceof TeamProfile) {
				return TngUtil.getPresentationName(((TeamProfile) e)
						.getSuperTeam());
			}
			else if (e instanceof RoleDescriptor && adapter instanceof ITreeItemContentProvider) {
				AdapterFactory adapterFactory = null;
				if(adapter instanceof BreakdownElementWrapperItemProvider) {
					adapterFactory = ((BreakdownElementWrapperItemProvider)adapter).getAdapterFactory();
				}
				else if(adapter instanceof ItemProviderAdapter) {
					adapterFactory = ((ItemProviderAdapter)adapter).getAdapterFactory();
				}
				return getTeamListString(getTeamProfiles(object, (ITreeItemContentProvider)adapter, adapterFactory));
 			}
		}
		if (property == IBSItemProvider.COL_ENTRY_STATE) {
			if (e instanceof WorkProductDescriptor) {
				WorkProductDescriptor wpd = (WorkProductDescriptor) e;
				return TngUtil.checkNull(wpd.getActivityEntryState());
			}
		} else if (property == IBSItemProvider.COL_EXIT_STATE) {
			if (e instanceof WorkProductDescriptor) {
				WorkProductDescriptor wpd = (WorkProductDescriptor) e;
				return TngUtil.checkNull(wpd.getActivityExitState());
			}
		} else if (property == IBSItemProvider.COL_DELIVERABLE) {
			if (e instanceof WorkProductDescriptor) {
				List deliverables = AssociationHelper
						.getDeliverableDescriptors((WorkProductDescriptor) e);
				if (deliverables.isEmpty())
					return ""; //$NON-NLS-1$
				StringBuffer strBuf = new StringBuffer();
				int max = deliverables.size() - 1;
				for (int i = 0; i < max; i++) {
					strBuf.append(
							TngUtil.getPresentationName(deliverables.get(i)))
							.append(',');
				}
				strBuf.append(TngUtil
						.getPresentationName(deliverables.get(max)));
				return strBuf.toString();
			}
		} else if (property == IBSItemProvider.COL_IS_OPTIONAL) {
			return String.valueOf(e.getIsOptional());
		} else if (property == IBSItemProvider.COL_IS_PLANNED) {
			return String.valueOf(e.getIsPlanned());
		} else if (property == IBSItemProvider.COL_HAS_MULTIPLE_OCCURRENCES) {
			return String.valueOf(e.getHasMultipleOccurrences());
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Get parent activity for team profile breakdown element
	 * UmaUtil.getParentActivity doesn't work correctly for sub-teams
	 * This method should only be used for breakdown elements under teamallocation
	 * @param team
	 * @return
	 */
	public static Object getParentActivityOfTeam(BreakdownElement brElement)
	{
		AdapterFactory adapterFactory = TngAdapterFactory.INSTANCE.getOBS_ComposedAdapterFactory();
		ItemProviderAdapter adapter = (ItemProviderAdapter) adapterFactory
				.adapt(brElement, ITreeItemContentProvider.class);
		Object parent = adapter.getParent(brElement);
		while (!(parent instanceof Activity)) {
			brElement = (BreakdownElement) parent;
			adapter = (ItemProviderAdapter) adapterFactory.adapt(brElement,
					ITreeItemContentProvider.class);
			parent = adapter.getParent(brElement);
		}

		return parent;	
	}
	
	
	/**
	 * Return roledescriptors under activity which could possible match for
	 * roles under the teams. It will recurse thru all child activities to find 
	 * role descriptors
	 * 
	 * @param adapterFactory
	 * @param parent
	 * @param roleDescList
	 * @param roles
	 */
	public static void getRoleDescriptor(AdapterFactory adapterFactory,
			Activity parent,  List roleDescList, List roles) {
		ItemProviderAdapter adapter = (ItemProviderAdapter) adapterFactory
				.adapt(parent, ITreeItemContentProvider.class);

		Object o = adapter.getChildren(parent);
		if (o instanceof List) {
			List children = (List) o;
			for (Iterator itor = children.iterator(); itor.hasNext();) {
				Object obj = itor.next();
				if (obj instanceof Activity) {
					getRoleDescriptor(adapterFactory, (Activity) obj,
							roleDescList, roles);
				}
				if (obj instanceof RoleDescriptor)
				{
					RoleDescriptor roleDesc = (RoleDescriptor) obj;
					if ((roleDesc.getRole()!= null) && 
							(roles.contains(roleDesc.getRole())))
						roleDescList.add(obj);
				}
			}
		}
	}
	
	private static String getTeamListString(List teamProfiles) {
		if (teamProfiles.isEmpty())
			return ""; //$NON-NLS-1$
		StringBuffer strBuf = new StringBuffer();
		int max = teamProfiles.size() - 1;
		for (int i = 0; i < max; i++) {
			strBuf.append(TngUtil.getPresentationName(teamProfiles.get(i)))
					.append(',');
		}
		strBuf.append(TngUtil.getPresentationName(teamProfiles.get(max)));
		return strBuf.toString();
	}

	public static void setAttribute(WorkBreakdownElement e, String prop,
			String txt) {
		if (prop == IBSItemProvider.COL_NAME) {
			e.setName(txt);
		} else if (prop == IBSItemProvider.COL_PREFIX) {
			e.setPrefix(txt);
		} else if (prop == IBSItemProvider.COL_IS_EVENT_DRIVEN) {
			e.setIsEventDriven(Boolean.valueOf(txt));
		} else if (prop == IBSItemProvider.COL_IS_ONGOING) {
			e.setIsOngoing(Boolean.valueOf(txt));
		} else if (prop == IBSItemProvider.COL_IS_REPEATABLE) {
			e.setIsRepeatable(Boolean.valueOf(txt));
		}
	}

	public static void setAttribute(IActionManager actionMgr,
			BreakdownElement e, String prop, String txt) {
		if (prop == IBSItemProvider.COL_NAME) {
			actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
					.getNamedElement_Name(), txt, -1);
		} else if (prop == IBSItemProvider.COL_PREFIX) {
			actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
					.getBreakdownElement_Prefix(), txt, -1);
		} else if (prop == IBSItemProvider.COL_IS_EVENT_DRIVEN) {
			actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
					.getWorkBreakdownElement_IsEventDriven(), Boolean
					.valueOf(txt), -1);
		} else if (prop == IBSItemProvider.COL_IS_ONGOING) {
			actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
					.getWorkBreakdownElement_IsOngoing(), Boolean.valueOf(txt),
					-1);
		} else if (prop == IBSItemProvider.COL_IS_REPEATABLE) {
			actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
					.getWorkBreakdownElement_IsRepeatable(), Boolean
					.valueOf(txt), -1);
		} else if (prop == IBSItemProvider.COL_PRESENTATION_NAME) {
			actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
					.getDescribableElement_PresentationName(), txt, -1);
		} else if (prop == IBSItemProvider.COL_IS_OPTIONAL) {
			actionMgr
					.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
							.getBreakdownElement_IsOptional(), Boolean
							.valueOf(txt), -1);
		} else if (prop == IBSItemProvider.COL_IS_PLANNED) {
			actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
					.getBreakdownElement_IsPlanned(), Boolean.valueOf(txt), -1);
		} else if (prop == IBSItemProvider.COL_HAS_MULTIPLE_OCCURRENCES) {
			actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
					.getBreakdownElement_HasMultipleOccurrences(), Boolean
					.valueOf(txt), -1);
		} else if (e instanceof WorkProductDescriptor) {
			if (prop == IBSItemProvider.COL_ENTRY_STATE) {
				actionMgr
						.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
								.getWorkProductDescriptor_ActivityEntryState(),
								txt, -1);
			} else if (prop == IBSItemProvider.COL_EXIT_STATE) {
				actionMgr.doAction(IActionManager.SET, e, UmaPackage.eINSTANCE
						.getWorkProductDescriptor_ActivityExitState(), txt, -1);
			}
		}

	}

	public static Activity generalize(Activity base, VariabilityType type) {
		Activity act = UmaFactory.eINSTANCE.createActivity();
		act.setName(base.getName());
		if (type == VariabilityType.LOCAL_REPLACEMENT_LITERAL) {
			String presentationName = getPresentationName(base);
			act.setPresentationName(StrUtil.isBlank(presentationName) ? base
					.getName() : presentationName);
		}
		act.setVariabilityBasedOnElement(base);
		act.setVariabilityType(type);

		if (type == VariabilityType.EXTENDS_LITERAL) {
			// inherit boolean attributes from base
			//
			for (Iterator iter = base.eClass().getEAllAttributes().iterator(); iter
					.hasNext();) {
				EAttribute attribute = (EAttribute) iter.next();
				if (attribute.getEAttributeType().getInstanceClass() == Boolean.class) {
					act.eSet(attribute, base.eGet(attribute));
				}
			}
		}

		// copy predecessors list
		// TODO: need to check with variability rules.
		//
		ArrayList workOrders = new ArrayList();
		for (Iterator iter = new ArrayList(base.getLinkToPredecessor())
				.iterator(); iter.hasNext();) {
			workOrders.add(TngUtil.copy((WorkOrder) iter.next()));
		}

		act.getLinkToPredecessor().addAll(workOrders);
		return act;
	}

	/**
	 * Returns list of elements specified in class "type" eg.(RoleDescriptor,
	 * WorkProductDescriptor" until the root level.
	 * 
	 * @param adapterFactory
	 * @param element
	 * @param type
	 * @param items
	 * @return
	 */
	public static List getElementsInScope(AdapterFactory adapterFactory,
			BreakdownElement element, Class type, List items) {
		// get children for activity
		ITreeItemContentProvider itemProvider = (ITreeItemContentProvider) adapterFactory
				.adapt(element, ITreeItemContentProvider.class);
		if (element instanceof Activity) {
			Collection children = ((Activity) element).getBreakdownElements();
			for (Iterator itor = children.iterator(); itor.hasNext();) {
				Object obj = itor.next();
				if (type.isInstance(obj)) {
					// System.out.println("Obj -" + obj);
					if (!(items.contains(obj))) {
						items.add(obj);
					}
				}
			}
		}

		// get parent
		Object currentParent = itemProvider.getParent(element);
		if (currentParent != null) {
			// go up
			getElementsInScope(adapterFactory,
					(BreakdownElement) currentParent, type, items);
		}
		return items;

	}

	/**
	 * Get roles from roledescriptor list
	 * 
	 * @param roleDescList
	 * @return
	 */

	public static List getRoles(List roleDescList) {
		List roleList = new ArrayList();
		if (roleDescList != null) {
			for (Iterator itor = roleDescList.iterator(); itor.hasNext();) {
				Object obj = itor.next();
				if (obj instanceof RoleDescriptor) {
					Role role = ((RoleDescriptor) obj).getRole();
					roleList.add(role);
				}
			}
		}
		return roleList;
	}

	/**
	 * Get associated method element list
	 * 
	 * @param descriptorList
	 * @return
	 */
	public static List getAssociatedElementList(List descriptorList) {
		List elementList = new ArrayList();
		if (descriptorList != null) {
			for (Iterator itor = descriptorList.iterator(); itor.hasNext();) {
				Object obj = itor.next();
				if (obj instanceof Descriptor) {
					MethodElement element = getAssociatedElement((Descriptor) obj);
					elementList.add(element);
				}
			}
		}
		return elementList;
	}

	public static BreakdownElement getTopBreakdownElement(ProcessComponent pc) {
		BreakdownElement be = pc.getProcess();
		if (be == null)
			return null;
		Object adapter = TngAdapterFactory.INSTANCE
				.getWBS_ComposedAdapterFactory().adapt(be,
						ITreeItemContentProvider.class);
		if (!(adapter instanceof IBSItemProvider))
			return be;
		IBSItemProvider itemProvider = (IBSItemProvider) adapter;
		if (itemProvider.getTopItem() == null) {
			itemProvider.setTopItem(be);
			itemProvider = (IBSItemProvider) TngAdapterFactory.INSTANCE
					.getOBS_ComposedAdapterFactory().adapt(be,
							ITreeItemContentProvider.class);
			itemProvider.setTopItem(be);
			itemProvider = (IBSItemProvider) TngAdapterFactory.INSTANCE
					.getPBS_ComposedAdapterFactory().adapt(be,
							ITreeItemContentProvider.class);
			itemProvider.setTopItem(be);
			itemProvider = (IBSItemProvider) TngAdapterFactory.INSTANCE
					.getProcessComposedAdapterFactory().adapt(be,
							ITreeItemContentProvider.class);
			itemProvider.setTopItem(be);
		}
		ProcessUtil.updateIDs(be, be);
		return be;
	}

	private static void updateIDs(EObject topAct, Object newObj) {
		ItemProviderAdapter adapter = (ItemProviderAdapter) TngAdapterFactory.INSTANCE
				.getWBS_ComposedAdapterFactory().adapt(topAct,
						ITreeItemContentProvider.class);
		AdapterFactory factory = TngUtil.getBestAdapterFactory(adapter
				.getAdapterFactory());
		boolean updateWholeProcess = topAct == newObj
				&& topAct instanceof Process;
		if (updateWholeProcess) {
			Process proc = (Process) topAct;
			updateIDs(factory, proc);
			refreshViewer(factory, proc);
		} else {
			AdapterFactoryTreeIterator iter = new AdapterFactoryTreeIterator(
					factory, topAct);
			updateIDs(factory, iter, newObj);
		}

		// No more ID column in TBS and WPBS
		//
		// adapter = (ItemProviderAdapter)
		// TngAdapterFactory.INSTANCE.getOBS_ComposedAdapterFactory().adapt(topAct,
		// ITreeItemContentProvider.class);
		// factory = TngUtil.getBestAdapterFactory(adapter.getAdapterFactory());
		// iter = new AdapterFactoryTreeIterator(factory, topAct);
		// ProcessUtil.updateIDs(factory, iter, newObj);
		// adapter = (ItemProviderAdapter)
		// TngAdapterFactory.INSTANCE.getPBS_ComposedAdapterFactory().adapt(topAct,
		// ITreeItemContentProvider.class);
		// factory = TngUtil.getBestAdapterFactory(adapter.getAdapterFactory());
		// iter = new AdapterFactoryTreeIterator(factory, topAct);
		// ProcessUtil.updateIDs(factory, iter, newObj);

		adapter = (ItemProviderAdapter) TngAdapterFactory.INSTANCE
				.getProcessComposedAdapterFactory().adapt(topAct,
						ITreeItemContentProvider.class);
		factory = TngUtil.getBestAdapterFactory(adapter.getAdapterFactory());
		if (updateWholeProcess) {
			Process proc = (Process) topAct;
			updateIDs(factory, proc);
			refreshViewer(factory, proc);
		} else {
			AdapterFactoryTreeIterator iter = new AdapterFactoryTreeIterator(
					factory, topAct);
			updateIDs(factory, iter, newObj);
		}
	}

	/**
	 * @param iter
	 * @param newObj
	 */
	public static void updateIDs(AdapterFactory factory,
			AdapterFactoryTreeIterator iter, Object newObj) {
		int id = 0;
		Object obj;
		Map changeMap = new HashMap();
		while (iter.hasNext()) {
			obj = iter.next();
			IBSItemProvider itemProvider = (IBSItemProvider) factory.adapt(obj,
					ITreeItemContentProvider.class);
			itemProvider.setId(id++);
			changeMap.put(obj, itemProvider);
		}

		// refresh the label
		//
		for (Iterator iterator = changeMap.entrySet().iterator(); iterator
				.hasNext();) {
			Map.Entry entry = (Map.Entry) iterator.next();
			IChangeNotifier adapter = (IChangeNotifier) entry.getValue();
			obj = entry.getKey();
			adapter.fireNotifyChanged(new ViewerNotification(
					new NotificationImpl(Notification.SET, obj, obj), obj,
					false, true));
		}
	}

	/**
	 * 
	 * @param descriptor
	 * @param obj
	 * @return
	 * @see #checkDescriptorReferences(Collection, Descriptor)
	 */
	public static boolean checkDescriptorReferences(Descriptor descriptor,
			Descriptor obj) {
		Collection descriptors = descriptor != null ? Collections
				.singleton(descriptor) : Collections.EMPTY_SET;
		return checkDescriptorReferences(descriptors, obj);
	}

	
	/**
	 * Check whether there are any references of the object "obj". If references
	 * exist in any descriptor in <code>descriptors</code>, ignore it.
	 * 
	 * @param descriptors
	 * @param obj
	 * @return
	 */
	public static boolean checkDescriptorReferences(Collection descriptors,
			Descriptor obj) {
		boolean referencesExists = false;

		if (obj instanceof RoleDescriptor) {
			RoleDescriptor refObject = (RoleDescriptor) obj;
			List list = new ArrayList();
			list.addAll(AssociationHelper.getAssistedTaskDescriptors(refObject));
			list.addAll(refObject.getResponsibleFor());
			list.addAll(AssociationHelper.getAdditionalTaskDescriptors(refObject));
			list.addAll(AssociationHelper.getPrimaryTaskDescriptors(refObject));
			list.addAll(AssociationHelper.getTeamProfiles(refObject));

			for (Iterator refItor = list.iterator(); refItor.hasNext();) {
				Object refItorObject = (Object) refItor.next();
				if (((refItorObject instanceof Descriptor) && !descriptors
						.contains(refItorObject))
						|| (refItorObject instanceof TeamProfile)) {
					referencesExists = true;
					break;
				}

			}
		} else if (obj instanceof WorkProductDescriptor) {		
			return checkWorkProductDescriptorReferences(descriptors, (WorkProductDescriptor) obj, false, -1);
		} else if (obj instanceof TaskDescriptor) {
			TaskDescriptor refObject = (TaskDescriptor) obj;
			List list = new ArrayList();
			list.addAll(refObject.getAdditionallyPerformedBy());
			list.addAll(refObject.getAssistedBy());
			list.addAll(refObject.getExternalInput());
			list.addAll(refObject.getMandatoryInput());
			list.addAll(refObject.getOptionalInput());
			list.addAll(refObject.getOutput());
			list.add(refObject.getPerformedPrimarilyBy());

			for (Iterator refItor = list.iterator(); refItor.hasNext();) {
				Object refItorObject = (Object) refItor.next();
				if ((refItorObject instanceof Descriptor)
						&& !descriptors.contains(refItorObject)) {
					referencesExists = true;
					break;
				}
			}
		}

		return referencesExists;
	}
	
	/**
	 * Check whether there are any references of the workProductdescriptor object "refObject. 
	 * If references exist in any descriptor in <code>descriptors</code>, ignore it.
	 * 
	 * @param descriptors
	 * @param refObject
	 * @param removeRelation - flag to indicate whether we're removing relation
	 *     By default this should be false. 
	 *     This is only applicable if you are coming from properties view. 
	 *     eg. removing relationship of work product descriptor to task descriptor 
	 * @param featureID
	 * 		This is only applicable if "removeRelation" is true. You need to give featureID
	 * 		for which relation you are removing.
	 * @return
	 */
	public static boolean checkWorkProductDescriptorReferences(
			Collection descriptors, WorkProductDescriptor refObject, boolean removeRelation, int featureID) {
		
		List allObjects = new ArrayList();
		allObjects.add(refObject);

		Activity parentActivity = UmaUtil.getParentActivity(refObject);
		// check whether reference object instance of artifact
		if (refObject.getWorkProduct() instanceof Artifact) {
			List containedArtifacts = ((Artifact) refObject.getWorkProduct())
					.getContainedArtifacts();

			List containedWpDescList = getWpDescForArtifacts(
					containedArtifacts, parentActivity);

			List containerArtifacts = new ArrayList();
			Artifact artifact = ((Artifact) refObject.getWorkProduct())
					.getContainerArtifact();
			while (artifact != null) {
				containerArtifacts.add(artifact);
				artifact = ((Artifact) artifact).getContainerArtifact();
			}
			List containerWpDescList = getWpDescForArtifacts(
					containerArtifacts, parentActivity);

			allObjects.addAll(containedWpDescList);
			allObjects.addAll(containerWpDescList);
		}

		for (int i = 0; i < allObjects.size(); i++) {
			WorkProductDescriptor wpObj = (WorkProductDescriptor) allObjects
					.get(i);

			List list = new ArrayList();
			list.addAll(wpObj.getImpactedBy());
			list.addAll(wpObj.getImpacts());
			list.addAll(AssociationHelper.getResponsibleRoleDescriptors(wpObj));
			list.addAll(wpObj.getDeliverableParts());

			List inputList = new ArrayList();
			inputList.addAll(AssociationHelper.getExternalInputTo(wpObj));
			inputList.addAll(AssociationHelper.getMandatoryInputTo(wpObj));
			inputList.addAll(AssociationHelper.getOptionalInputTo(wpObj));

			List outputList = AssociationHelper.getOutputFrom(wpObj);
			if (removeRelation)
			{
				switch (featureID) {
				case UmaPackage.TASK_DESCRIPTOR__EXTERNAL_INPUT:
				case UmaPackage.TASK_DESCRIPTOR__MANDATORY_INPUT:
				case UmaPackage.TASK_DESCRIPTOR__OPTIONAL_INPUT:
					if (outputList.containsAll(descriptors))
						return true;
					break;
				case UmaPackage.TASK_DESCRIPTOR__OUTPUT :				
					if (inputList.containsAll(descriptors))
						return true;
				}
			}

			list.addAll(inputList);
			list.addAll(outputList);
			
			for (Iterator refItor = list.iterator(); refItor.hasNext();) {
				Object refItorObject = (Object) refItor.next();
				if ((refItorObject instanceof Descriptor)
						&& !descriptors.contains(refItorObject)) {
					return true;
				}
			}
		}
		return false;
	}

	
	/**
	 * Return list of corresponding work product descriptors for artifacts
	 * @param artifacts
	 * @param parentActivity
	 * @return
	 */
	public static List getWpDescForArtifacts(List artifacts, Activity parentActivity)
	{
		List wpDescList = new ArrayList();
		for (int i=0; i < artifacts.size(); i++)
		{
			Artifact artifact = (Artifact) artifacts.get(i);
			List brElements = parentActivity.getBreakdownElements();
			for (Iterator itor = brElements.iterator(); itor.hasNext();)
			{
				Object brObj = (Object) itor.next();
				if (brObj instanceof WorkProductDescriptor) 
				{
					WorkProductDescriptor wpDesc = (WorkProductDescriptor) brObj;
					if (wpDesc.getWorkProduct() instanceof Artifact)
					{
						if (wpDesc.getWorkProduct().equals(artifact))
							wpDescList.add(wpDesc);
					}
				}
			}
		}
		return wpDescList;
	}

	public static CompositeRole createCompositeRole(CompositeRole obj) {
		CompositeRole compRole = UmaFactory.eINSTANCE.createCompositeRole();
		compRole.getAggregatedRoles().addAll(obj.getAggregatedRoles());

		String presentationName = obj.getPresentationName();
		compRole.setName(obj.getName());
		compRole.setPresentationName(StrUtil.isBlank(presentationName) ? obj
				.getName() : presentationName);
		return compRole;
	}

	public static void addTaskToActivity(Task task, Activity act) {
		WBSDropCommand cmd = new WBSDropCommand(act, Collections
				.singletonList(task));
		BSDropCommand.IExecutor executor = cmd.getExecutor();
		if (executor.preExecute()) {
			executor.doExcecute();
		}
	}

	public static boolean hasProcessNotOfType(ProcessPackage pkg,
			EClass processType) {
		if (pkg instanceof ProcessComponent) {
			Process proc = ((ProcessComponent) pkg).getProcess();
			if (proc != null && !processType.isInstance(proc)) {
				return true;
			}
		}
		for (Iterator iterator = pkg.getChildPackages().iterator(); iterator
				.hasNext();) {
			Object childPkg = iterator.next();
			if (childPkg instanceof ProcessComponent) {
				Process proc = ((ProcessComponent) childPkg).getProcess();
				if (proc != null && !processType.isInstance(proc)) {
					return true;
				}
			} else if (childPkg instanceof ProcessPackage) {
				if (hasProcessNotOfType((ProcessPackage) childPkg, processType)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Find correspoding roleDescriptor in team since we maintain two role
	 * descriptor for the same role
	 * 
	 * @param team
	 * @param roleDesc
	 * @return
	 */
	public static Object findRoleDescriptor(TeamProfile team,
			RoleDescriptor roleDesc) {
		List teamRoles = team.getTeamRoles();

		for (Iterator itor = teamRoles.iterator(); itor.hasNext();) {
			Object itorObject = itor.next();
			if (roleDesc instanceof CompositeRole) {
				if (itorObject instanceof CompositeRole) {
					List firstObjectAggRoles = ((CompositeRole) roleDesc)
							.getAggregatedRoles();
					List secondObjectAggRoles = ((CompositeRole) itorObject)
							.getAggregatedRoles();
					if (firstObjectAggRoles.equals(secondObjectAggRoles)) {
						return itorObject;
					}
				}
			} else if (roleDesc instanceof RoleDescriptor) {
				if ((itorObject instanceof RoleDescriptor)
						&& (!(itorObject instanceof CompositeRole))) {
					Object objRole = ((RoleDescriptor) roleDesc).getRole();
					Object itorObjRole = ((RoleDescriptor) itorObject)
							.getRole();
					if (objRole.equals(itorObjRole)) {
						return itorObject;
					}
				}
			}
		}

		return null;
	}

	/**
	 * Creates a columnIndexToNameMap from the comma-separated list of column
	 * names
	 * 
	 * @param newValue
	 * @return
	 */
	public static Map toColumnIndexToNameMap(String colNames) {
		Map columnIndexToNameMap = new HashMap();
		StringTokenizer tokens = new StringTokenizer(colNames, ","); //$NON-NLS-1$
		int id = 0;
		while (tokens.hasMoreTokens()) {
			String token = tokens.nextToken();
			columnIndexToNameMap.put(new Integer(id), getColumnID(token));
			id++;
		}
		return columnIndexToNameMap;
	}

	/**
	 * @param token
	 * @return
	 */
	private static String getColumnID(String colName) {
		for (int i = 0; i < IBSItemProvider.COLUMNS.length; i++) {
			String col = IBSItemProvider.COLUMNS[i];
			if (col.equals(colName)) {
				return col;
			}
		}
		return null;
	}

	// This method is used to check whether an new descriptor can be created for a given method element
	// under the given activity, considering all inherited descriptors of the activity.
	// It is NOT EFFICIENT to collect all linked elements of the inherited descriptors into a list and then check if
	// whether the given method element is in the list.
	//
	// Use ProcessCommandUtil#getValidDescriptor(Object obj, Activity activity) instead
	//
//	public static List getVariabilityElement(Object owner) {
//		List baseElements = new ArrayList();
//		if (owner instanceof Activity) {
//			Activity activity = (Activity) owner;
//			while (!activity.getVariabilityType().equals(
//					VariabilityType.NA_LITERAL)) {
//				VariabilityElement element = activity
//						.getVariabilityBasedOnElement();
//
//				if ((element != null) && (element instanceof Activity)) {
//					Activity baseActivity = (Activity) element;
//
//					List breakdownElements = baseActivity
//							.getBreakdownElements();
//					for (Iterator itor = breakdownElements.iterator(); itor
//							.hasNext();) {
//						Object object = itor.next();
//						if (object instanceof Descriptor) {
//							Object baseObj = getAssociatedElement((Descriptor) object);
//							if (baseObj != null) {
//								baseElements.add(baseObj);
//							}
//						}
//					}
//
//					activity = baseActivity;
//				}
//				else {
//					break;
//				}
//			}
//		}
//
//		return baseElements;
//	}

	/**
	 * Refreshes predecessor list of all item providers of the given process
	 * 
	 * @param factory
	 * @param proc
	 * @param elements
	 */
	public static void removePredecessors(AdapterFactory factory, Process proc,
			List removedElements) {
		HashSet elements = new HashSet(removedElements);
		for (Iterator iter = new AdapterFactoryTreeIterator(factory, proc); iter
				.hasNext();) {
			Object obj = iter.next();
			IBSItemProvider itemProvider = (IBSItemProvider) factory.adapt(obj,
					ITreeItemContentProvider.class);
			if (itemProvider != null
					&& TngUtil.unwrap(obj) instanceof WorkBreakdownElement) {
				for (Iterator iterator = itemProvider.getPredecessors()
						.iterator(); iterator.hasNext();) {
					Object e = TngUtil.unwrap(iterator.next());
					if (e instanceof ItemProviderAdapter) {
						e = ((ItemProviderAdapter) e).getTarget();
					}
					if (elements.contains(e)) {
						iterator.remove();
					}
				}
			}
		}

	}

	private static void addToActivity(Activity act, BreakdownElement be, Object[] prevAndNext) {
		Object next = prevAndNext[1];
		boolean added = false;
		if(next != null) {
			int id = act.getBreakdownElements().indexOf(next);
			if(id != -1) { 
				act.getBreakdownElements().add(id, be);
				added = true;
			}
		}
		if(!added) {
			Object prev = prevAndNext[0];
			if(prev != null) {				
				int id = act.getBreakdownElements().indexOf(prev);
				if(id != -1) {
					act.getBreakdownElements().add(id + 1, be);
				}
				else {
					act.getBreakdownElements().add(be);
				}
			}
			else {
				act.getBreakdownElements().add(be);
			}
		}

	}
	
	/**
	 * Locally contributes to the inherited activity represented by the given adapter
	 * 
	 * @param adapter
	 * @param createdActivities
	 * @return
	 */
	public static Activity contributeToActivity(
			BreakdownElementWrapperItemProvider adapter, List createdActivities) {
		Object parent = adapter.getParent(null);
		Object[] prevAndNext = ProcessUtil
				.getPreviousAndNext(adapter);
		if (parent instanceof BreakdownElementWrapperItemProvider) {
			parent = contributeToActivity(
					(BreakdownElementWrapperItemProvider) parent,
					createdActivities);
		}
		Activity act = ProcessUtil.generialize(adapter,
				VariabilityType.LOCAL_CONTRIBUTION_LITERAL, prevAndNext);
		Activity parentAct = ((Activity) parent);
		addToActivity(parentAct, act, prevAndNext);
		createdActivities.add(act);
		return act;
	}

	/**
	 * Locally replaces the inherited activity represented by the given adapter
	 * 
	 * @param adapter
	 * @param createdActivities
	 */
	public static void replaceActivityLocally(
			BreakdownElementWrapperItemProvider adapter, List createdActivities) {
		Object parent = adapter.getParent(null);
		Object[] prevAndNext = ProcessUtil
				.getPreviousAndNext(adapter);
		if (parent instanceof BreakdownElementWrapperItemProvider) {
			parent = contributeToActivity(
					(BreakdownElementWrapperItemProvider) parent,
					createdActivities);
		}
		Activity act = ProcessUtil.generialize(adapter,
				VariabilityType.LOCAL_REPLACEMENT_LITERAL, prevAndNext);
		Activity parentAct = ((Activity) parent);
		addToActivity(parentAct, act, prevAndNext);
		createdActivities.add(act);
	}

	static Object[] getPreviousAndNext(
			BreakdownElementWrapperItemProvider adapter) {
		Object parent = adapter.getParent(null);
		AdapterFactory adapterFactory = TngUtil.getBestAdapterFactory(adapter
				.getAdapterFactory());
		ITreeItemContentProvider itemProvider = (ITreeItemContentProvider) adapterFactory
				.adapt(parent, ITreeItemContentProvider.class);
		List children = (List) itemProvider.getChildren(parent);
		int id = children.indexOf(adapter) + 1;
		Object next = null;
		if (id < children.size()) {
			next = children.get(id);
		}
		Object prev = null;
		id -= 2;
		if (id > -1) {
			prev = children.get(id);
		}

		Object[] prevAndNext = { prev, next };
		return prevAndNext;
	}

	static Activity generialize(BreakdownElementWrapperItemProvider adapter,
			VariabilityType type, Object[] prevAndNext) {
		AdapterFactory adapterFactory = TngUtil.getBestAdapterFactory(adapter
				.getAdapterFactory());

		Activity act = generalize((Activity) adapter.getValue(), type);
		Object next = prevAndNext[1];
		if(next != null) {
			act.setPresentedAfter((BreakdownElement) TngUtil.unwrap(next));
			if(next instanceof BreakdownElement) {
				((BreakdownElement)next).setPresentedBefore(act);
			}
		}
		Object prev = prevAndNext[0];
		if(prev != null) {
			act.setPresentedBefore((BreakdownElement) TngUtil.unwrap(prev));
			if (prev instanceof BreakdownElement) {
				((BreakdownElement)prev).setPresentedAfter(act);
			}
		}
		IBSItemProvider bsItemProvider = (IBSItemProvider) adapterFactory
				.adapt(act, ITreeItemContentProvider.class);
		bsItemProvider.setExpanded(adapter.isExpanded());
		return act;
	}

	/**
	 * Gets the immediate base process of the given
	 * BreakdownElementWrapperItemProvider that represents an inherited
	 * breakdown element.
	 * 
	 * @param itemProvider
	 * @return
	 */
	public static Process getImmediateBaseProcess(
			BreakdownElementWrapperItemProvider itemProvider) {
		Activity inheritor = getInheritor(itemProvider);
		if (inheritor != null) {
			return TngUtil.getOwningProcess((BreakdownElement) inheritor
					.getVariabilityBasedOnElement());
		}
		return null;
	}

	/**
	 * Gets the activity in the process of the given item provider that inherits
	 * the element represented by the given item provider
	 * 
	 * @param itemProvider
	 * @return
	 */
	public static Activity getInheritor(
			BreakdownElementWrapperItemProvider itemProvider) {
		if (itemProvider.isReadOnly()) {
			// this represents an inherited breakdown element
			//
			for (Object parent = itemProvider.getParent(itemProvider); parent != null;) {
				if (parent instanceof BreakdownElementWrapperItemProvider) {
					parent = ((BreakdownElementWrapperItemProvider) parent)
							.getParent(parent);
				} else {
					return (Activity) parent;
				}
			}
		}
		return null;
	}

	/**
	 * Gets parent list of <code>wrapper</code> from <code>from</code>,
	 * excluded <code>from</code>
	 * 
	 * @param from
	 * @param wrapper
	 * @return list of unwrapped parent objects
	 */
	public static List getParentList(Object from,
			BreakdownElementWrapperItemProvider wrapper) {
		return getParentList(wrapper, from, wrapper.getAdapterFactory());
	}
	
	/**
	 * Gets parent list of <code>object</code> from <code>from</code>,
	 * excluded <code>from</code>
	 * 
	 * @param object
	 * @param from
	 * @param adapterFactory
	 * @return list of unwrapped parent objects
	 */
	public static List getParentList(Object object, Object from, AdapterFactory adapterFactory) {
		ArrayList parentList = new ArrayList();
		ITreeItemContentProvider itemProvider = (ITreeItemContentProvider) adapterFactory.adapt(object, ITreeItemContentProvider.class);
		for (Object parent = itemProvider.getParent(object); parent != from
				&& parent != null;) {
			Object obj = TngUtil.unwrap(parent);
			MethodElement e;			
			if (obj instanceof MethodElement) {
				e = (MethodElement) obj;
				ITreeItemContentProvider adapter;
				if (parent instanceof ITreeItemContentProvider) {
					adapter = (ITreeItemContentProvider) parent;
				} else {
					adapter = (ITreeItemContentProvider) adapterFactory.adapt(
							parent, ITreeItemContentProvider.class);
				}
				if(ProcessUtil.isTopProcess(e)) {
					parent = null;
				}
				else {
					parent = adapter.getParent(parent);
				}
			} else {
				// must be a ItemProviderAdapter
				//
				ItemProviderAdapter adapter = ((ItemProviderAdapter) obj);
				e = (MethodElement) adapter.getTarget();
				parent = adapter.getParent(parent);
			}
			parentList.add(0, e);
		}
		return parentList;
	}

	/**
	 * Gets the wrappers of all breakdown structure (BS) views in the following
	 * order: WBS, TBS, WPBS
	 * 
	 * @param wrapper
	 *            the wrapper of a BS view
	 * @return
	 */
	public static List getWrappers(BreakdownElementWrapperItemProvider wrapper, AdapterFactory[] adapterFactories) {
		ArrayList rolledUpItemProviders = new ArrayList();
		try {
			AdapterFactory rootAdapterFactory = TngUtil.getBestAdapterFactory(wrapper.getAdapterFactory());
			Object proc = wrapper.getTopItem();						
			ArrayList objects = new ArrayList(ProcessUtil.getParentList(proc,
					wrapper));
			ArrayList wrappers = new ArrayList();
			for (int i = 0; i < adapterFactories.length; i++) {
				AdapterFactory adapterFactory = adapterFactories[i];
				if (adapterFactory == rootAdapterFactory) {
					wrappers.add(wrapper);
					continue;
				}
				Object e = TngUtil.unwrap(wrapper);
				objects.add(e);
				Object object = proc;
				for (Iterator iter1 = objects.iterator(); iter1.hasNext();) {
					Object element = iter1.next();
					ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory
					.adapt(object, ITreeItemContentProvider.class);
					
					// make sure the activity is rolled down before looking into its children
					//
					Object be = TngUtil.unwrap(object);								
					if(be instanceof Activity) {
						if(adapter instanceof BSActivityItemProvider) {
							BSActivityItemProvider itemProvider = (BSActivityItemProvider) adapter;
							if(itemProvider.isRolledUp()) {
								itemProvider.basicSetRolledUp(false);
								rolledUpItemProviders.add(itemProvider);
							}
						}
						else if(adapter instanceof IBSItemProvider) {
							IBSItemProvider itemProvider = (IBSItemProvider) adapter;
							if(itemProvider.isRolledUp()) {
								itemProvider.setRolledUp(false);
								rolledUpItemProviders.add(itemProvider);
							}
						}
					}
					
					find_child: for (Iterator iterator = adapter
							.getChildren(object).iterator(); iterator.hasNext();) {
						Object child = iterator.next();
						if (element == TngUtil.unwrap(child)) {
							object = child;
							break find_child;
						}
					}
				}
				if (object instanceof BreakdownElementWrapperItemProvider) {
					wrappers.add(object);
				} else {
					throw new RuntimeException(
							"Could not find wrapper for " + e + " using adapter factory " + adapterFactory); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
			return wrappers;
		}
		finally {
			if(!rolledUpItemProviders.isEmpty()) {
				// restore the rolledUp flag
				//
				for (Iterator iter = rolledUpItemProviders.iterator(); iter
				.hasNext();) {
					((BSActivityItemProvider) iter.next()).basicSetRolledUp(true);
				}
			}
		}
	}
	
	/**
	 * Gets WorkProductDescriptor specific model info 
	 * @param modelInfo
	 * @param object WorkProductDescriptor or its wrapper
	 * @param itemProvider item provider of WorkProductDescriptor or its wrapper
	 */
	public static void getWPDModelInfo(StringBuffer modelInfo, Object object, Object itemProvider) {
		Object element = TngUtil.unwrap(object);
		if(element instanceof WorkProductDescriptor) {	
			WorkProductDescriptor wpd = (WorkProductDescriptor)element;
			if(itemProvider instanceof ITreeItemContentProvider) {
				// check if this work product descriptor is shown under a task descriptor or role descriptor
				//
				AdapterFactory adapterFactory = null;
				if(itemProvider instanceof ItemProviderAdapter) {
					adapterFactory = ((ItemProviderAdapter)itemProvider).getAdapterFactory();
				}
				else if(itemProvider instanceof BreakdownElementWrapperItemProvider) {
					adapterFactory = ((BreakdownElementWrapperItemProvider)itemProvider).getAdapterFactory();
				}
				if(adapterFactory != null) {
					Object parentDescriptor = null;
					ITreeItemContentProvider adapter = (ITreeItemContentProvider)itemProvider;
					findParentDescriptor:
						for(Object parent = adapter.getParent(object); parent != null; parent = adapter.getParent(parent)) {
							Object e = TngUtil.unwrap(parent);
							if(e instanceof TaskDescriptor) {
								parentDescriptor = e;
								break findParentDescriptor;
							}
							else if(e instanceof Activity) {
								break findParentDescriptor;
							}
							adapter = (ITreeItemContentProvider) adapterFactory.adapt(parent, ITreeItemContentProvider.class);
						}
					if(parentDescriptor != null) {	
						// work product descriptor is shown under a task descriptor
						// show only model info related to this task descriptor
						//
						ArrayList features = new ArrayList();
						if(AssociationHelper.getMandatoryInputTo(wpd).contains(parentDescriptor)) {
							features.add(UmaPackage.eINSTANCE.getTaskDescriptor_MandatoryInput());
						}
						if(AssociationHelper.getOptionalInputTo(wpd).contains(parentDescriptor)) {
							features.add(UmaPackage.eINSTANCE.getTaskDescriptor_OptionalInput());							
						}
						if(AssociationHelper.getOutputFrom(wpd).contains(parentDescriptor)) {
							features.add(UmaPackage.eINSTANCE.getTaskDescriptor_Output());
						}
						if(!features.isEmpty()) {
							if (modelInfo.toString().length() > 0) {
								modelInfo.append(","); //$NON-NLS-1$
							}
							for (int i = 0; i < features.size(); i++) {
								EStructuralFeature feature = (EStructuralFeature) features.get(i);
								modelInfo.append(TngUtil.getFeatureText(feature));
								if(i < features.size() -1){
									modelInfo.append(",");
								}
							}						
						}
						return;
					}
				}
			}
			getModelInfoForWorkProductDescriptor(modelInfo, wpd);
		}
	}

	/**
	 * Retrieves the ModelInformation specific to WorkProductDescriptor. Model
	 * Information is for PBS (WorkProductDescriptors, including Extended
	 * Activity's WorkProductDescriptors).
	 */
	private static void getModelInfoForWorkProductDescriptor(
			StringBuffer modelInfo, WorkProductDescriptor object) {
		String comma = ","; //$NON-NLS-1$
		if (!AssociationHelper.getMandatoryInputTo(object).isEmpty()) {
			if (modelInfo.toString().length() > 0) {
				modelInfo.append(comma);
			}
			modelInfo.append(UmaEditPlugin.INSTANCE
					.getString("_UI_TaskDescriptor_mandatoryInput_feature")); //$NON-NLS-1$
		}
		if (!AssociationHelper.getOptionalInputTo(object).isEmpty()) {
			if (modelInfo.toString().length() > 0) {
				modelInfo.append(comma);
			}
			modelInfo.append(UmaEditPlugin.INSTANCE
					.getString("_UI_TaskDescriptor_optionalInput_feature")); //$NON-NLS-1$
		}
		if (!AssociationHelper.getOutputFrom(object).isEmpty()) {
			if (modelInfo.toString().length() > 0) {
				modelInfo.append(comma);
			}
			modelInfo.append(UmaEditPlugin.INSTANCE
					.getString("_UI_TaskDescriptor_output_feature")); //$NON-NLS-1$
		}
	}

	public static Collection getDuplicateDescriptorsAfterReveal(Collection elementsToReveal) {
		Collection duplicates = new ArrayList();
		for (Iterator iter = elementsToReveal.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if(element instanceof Descriptor) {
				Descriptor desc = (Descriptor) element;
				MethodElement e = ProcessUtil.getAssociatedElement(desc);
				if(e != null) {
					Activity act = UmaUtil.getParentActivity(desc);
					MethodConfiguration config = TngUtil.getOwningProcess(act).getDefaultContext();
					e = (MethodElement) Providers.getConfigurationApplicator().resolve(e, config);
					Object duplicate = ProcessCommandUtil.getDescriptor(e, act, config);
					if(duplicate != null) {
						duplicates.add(duplicate);
					}
				}
			}
		}
		
		return duplicates;
	}
	
	public static Collection getDuplicateDescriptorsAfterSuppress(Collection elementsToSuppress) {
		Collection duplicates = new ArrayList();
		for (Iterator iter = elementsToSuppress.iterator(); iter.hasNext();) {
			Object item = iter.next();
			if(item instanceof Descriptor) {
				Descriptor desc = (Descriptor) item;
				MethodElement e = ProcessUtil.getAssociatedElement(desc);
				if(e != null) {
					Activity act = UmaUtil.getParentActivity(desc);
					for (Iterator iterator = act.getBreakdownElements().iterator(); iterator.hasNext();) {
						BreakdownElement element = (BreakdownElement) iterator.next();
						if(element != e && element instanceof Descriptor && element.getSuppressed().booleanValue()) {
							MethodElement linkedElement = ProcessUtil.getAssociatedElement((Descriptor) element);
							if(linkedElement == e) {
								duplicates.add(element);
							}
						}
					}
				}
			}
		}
		
		return duplicates;
		
	}

	/**
	 * Checks if the given object is representing a inherited element in a breakdown structure tree of process editor
	 * 
	 * @param object
	 * @return
	 */
	public static boolean isInherited(Object object) {
		return object instanceof DescribableElementWrapperItemProvider
		&& ((DescribableElementWrapperItemProvider)object).isInherited();
	}
	
	/**
	 * Checks if the given activity has inherited any breakdown element via extension of local contribution
	 * 
	 * @param activity
	 * @return
	 */
	public static boolean hasInherited(Activity activity) {
		Iterator iter = new AbstractTreeIterator(activity) {

			/**
			 * Comment for <code>serialVersionUID</code>
			 */
			private static final long serialVersionUID = 0L;

			protected Iterator getChildren(Object object) {
				if(object instanceof Activity) {
					return ((Activity)object).getBreakdownElements().iterator();
				}
				return Collections.EMPTY_LIST.iterator();
			}
			
		};
		while(iter.hasNext()) {
			Object o = iter.next();
			if(o instanceof Activity) {
				Activity act = (Activity) o;
				VariabilityElement ve = act.getVariabilityBasedOnElement();
				if(ve != null) {
					VariabilityType type = act.getVariabilityType();
					if(type == VariabilityType.EXTENDS_LITERAL || type == VariabilityType.LOCAL_CONTRIBUTION_LITERAL) {
						return true;
					}
				}
			}
		}
		return false;
	}
	
	public static boolean isContributed(Object object) {
		return object instanceof BreakdownElementWrapperItemProvider
		&& ((BreakdownElementWrapperItemProvider)object).isContributed();
	}	
	
	public static void getAllSubTeams(TeamProfile team, List teams) {
		teams.add(team);
		List subTeams = team.getSubTeam();
		for (Iterator itor = subTeams.iterator(); itor.hasNext();) {
			TeamProfile subTeam = (TeamProfile) itor.next();

			getAllSubTeams(subTeam, teams);
		}
	}
	
	private static List getTeamProfiles(Object object, ITreeItemContentProvider adapter, AdapterFactory adapterFactory) {
		RoleDescriptor roleDesc = (RoleDescriptor) TngUtil.unwrap(object);
		List teams = new ArrayList(AssociationHelper.getTeamProfiles(roleDesc));
		
		// get all the team profiles that are in scope of the wrapper
		//
		HashSet visibleTeams = new HashSet();
		for (Object parent = adapter.getParent(object); parent != null;) {
			adapter = (ITreeItemContentProvider) adapterFactory.adapt(parent, ITreeItemContentProvider.class);		
			for (Iterator iter = adapter.getChildren(parent).iterator(); iter.hasNext();) {
				Object e = TngUtil.unwrap(iter.next());
				if (e instanceof TeamProfile) {
					List activityTeams = new ArrayList();
					getAllSubTeams((TeamProfile) e, activityTeams);
					for (Iterator itor = activityTeams.iterator(); itor.hasNext();)	{
						Object o = itor.next();
						if(o instanceof TeamProfile && ((TeamProfile)o).getTeamRoles().contains(roleDesc)) {
							visibleTeams.add(o);
						}
					}
				}
			}
			Object newParent = adapter.getParent(parent);
			if(newParent == null && parent instanceof Activity) {
				newParent = UmaUtil.getParentActivity((Activity)parent);
			}
			parent = newParent;
		}
		
		// remove any team profile that is not in the scope of the wrapper
		//
		for (Iterator iter = teams.iterator(); iter.hasNext();) {
			Object team = iter.next();
			if(!visibleTeams.contains(team)) {
				iter.remove();
			}
		}
		
		return teams;

	}
	
	/**
	 * Gets the list of visible team profiles for the role descriptor represented by the given wrapper
	 * 
	 * @param roleDescWrapper
	 * @return
	 */
	public static List getTeamProfiles(RoleDescriptorWrapperItemProvider roleDescWrapper) {
		return getTeamProfiles(roleDescWrapper, roleDescWrapper, roleDescWrapper.getAdapterFactory());
	}
	
	public static List getTeamProfiles(RoleDescriptor roleDesc, AdapterFactory adapterFactory) {
		ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory.adapt(roleDesc, ITreeItemContentProvider.class);
		return getTeamProfiles(roleDesc, adapter, adapterFactory);
	}
	
	public static void getChildElements(Activity act, Class type, Collection collection) {
		for (int i = act.getBreakdownElements().size() - 1; i > -1; i--) {
			Object element = act.getBreakdownElements().get(i);
			if(type.isInstance(element)) {
				collection.add(element);
			}
			else if(element instanceof Activity) {
				getChildElements((Activity) element, type, collection);
			}
		}
	}
	
	public static IFilter getFilter(AdapterFactory adapterFactory) {
		AdapterFactory rootAdapterFactory = TngUtil.getBestAdapterFactory(adapterFactory);
		if(rootAdapterFactory instanceof ConfigurableComposedAdapterFactory) {
			return ((ConfigurableComposedAdapterFactory)rootAdapterFactory).getFilter();
		}
		return null;
	}
	
	/**
	 * Gets the calculated list of artifact contained by the given artifact based on the
	 * configuration associated with the given adapter factory.
	 * 
	 * @param artifact
	 * @param adapterFactory
	 * @return
	 */
	public static List getContainedArtifacts(Artifact artifact, AdapterFactory adapterFactory) {
		MethodConfiguration config = null;
		IFilter filter = ProcessUtil.getFilter(adapterFactory);
		if(filter instanceof IConfigurator) {
			config = ((IConfigurator)filter).getMethodConfiguration();
		}
		
		if(config == null) {
			return artifact.getContainedArtifacts();
		}
		else {
			return (List) Providers.getConfigurationApplicator().getReference(
					artifact,
					UmaPackage.eINSTANCE.getArtifact_ContainedArtifacts(),
					config);
		}		
	}
	
	public static List getContainedArtifactsDescriptors(WorkProductDescriptor artifactDesc, List artifactDescriptors) {
		if(artifactDescriptors.isEmpty()) {
			return Collections.EMPTY_LIST;
		}
		Artifact artifact = (Artifact) artifactDesc.getWorkProduct();
		
		// collect own and contributing subartifact descriptors
		//
		ArrayList containedDescriptors = new ArrayList();
		for(int i = artifactDescriptors.size() - 1; i > -1; i--) {
			WorkProductDescriptor wpd = ((WorkProductDescriptor)artifactDescriptors.get(i));
			WorkProduct a = wpd.getWorkProduct();
			if(a != null) {
				EObject container = a.eContainer();
				if(container == artifact || 
						(container instanceof Artifact && TngUtil.isContributorOf(artifact, (Artifact) container))) {
					containedDescriptors.add(wpd);
				}
			}
		}
		return containedDescriptors;
	}
	
//	public static boolean isContainedBy(Artifact parent, Artifact child, AdapterFactory adapterFactory) {
//		MethodConfiguration config = null;
//		IFilter filter = ProcessUtil.getFilter(adapterFactory);
//		if(filter instanceof IConfigurator) {
//			config = ((IConfigurator)filter).getMethodConfiguration();
//		}
//		
//		if(config == null) {
//			return UmaUtil.isContainedBy(child, parent);
//		}
//		
//		final MethodConfiguration cfg = config;		
//		Iterator iter = new AbstractTreeIterator(parent, false) {
//
//			/**
//			 * Comment for <code>serialVersionUID</code>
//			 */
//			private static final long serialVersionUID = 1L;
//
//			protected Iterator getChildren(Object object) {
//				return ((Collection) Providers.getConfigurationApplicator().getReference(
//						(VariabilityElement) object,
//						UmaPackage.eINSTANCE.getArtifact_ContainedArtifacts(),
//						cfg)).iterator();
//			}
//			
//		};
//		while(iter.hasNext()) {
//			if(child == iter.next()) {
//				return true;
//			}
//		}
//		
//		return false;
//	}
	
	/**
	 * Checks if the given WorkProductDescriptor <code>parent</code> can represent the parent of the WorkProductDescriptor
	 * <code>child</code> based on the relationship of their linked artifact and the list of available artifact descriptors
	 */
	public static boolean isContainedBy(WorkProductDescriptor parent, WorkProductDescriptor child, final List artifactDescList) {
//		Iterator iter = new AbstractTreeIterator(parent, false) {
//			
//			/**
//			 * Comment for <code>serialVersionUID</code>
//			 */
//			private static final long serialVersionUID = 1L;
//			
//			protected Iterator getChildren(Object object) {
//				return getContainedArtifactsDescriptors((WorkProductDescriptor) object, artifactDescList).iterator();
//			}
//			
//		};
//		while(iter.hasNext()) {
//			if(child == iter.next()) {
//				return true;
//			}
//		}
//		
//		return false;
		
		return UmaUtil.isContainedBy(child.getWorkProduct(), parent.getWorkProduct());
	}

	public static List removeSubartifactsFromChildren(final Collection children, boolean unwrap) {
		List artifactList = new ArrayList();
	
		// get the artifact list
		//
		for (Iterator iter = children.iterator(); iter.hasNext();) {
			Object child = iter.next();
			if(unwrap) {
				child = TngUtil.unwrap(child);
			}
			if (child instanceof WorkProductDescriptor) {
				WorkProduct wp = ((WorkProductDescriptor) child)
						.getWorkProduct();
				if (wp instanceof Artifact) {
					artifactList.add(wp);
				}
			}
		}
	
		// process the artifact list to get the top-most ones
		//
		Set topMostArtifacts = new HashSet();
		Artifact candidate = null;
	
		boolean found = false;
		while (!artifactList.isEmpty()) {
			
			if (!found)
			{
				candidate = (Artifact) artifactList.get(0);
				artifactList.remove(0);
			}
			for (Iterator iter = artifactList.iterator(); iter.hasNext();) {
				Artifact artifact = (Artifact) iter.next();
				found = false;
				// if(candidate.getContainedArtifacts().contains(artifact)) {
				if (UmaUtil.isContainedBy(artifact, candidate)) {
					iter.remove();
				}
				else if (UmaUtil.isContainedBy(candidate, artifact)) {
					iter.remove();
					candidate = artifact;
					found = true;
					break;
				}
			}
			if (!found || artifactList.isEmpty())
				topMostArtifacts.add(candidate);
			else if (artifactList.isEmpty())
					topMostArtifacts.add(candidate);		
		}
	
		List result = new ArrayList();
		for (Iterator ci = children.iterator(); ci.hasNext();) {
			Object child = ci.next();
			Object e = unwrap ? TngUtil.unwrap(child) : child;
			boolean selected = false;
			if (e instanceof WorkProductDescriptor) {
				WorkProductDescriptor wpd = ((WorkProductDescriptor) e);
				WorkProduct wp = wpd.getWorkProduct();
				if (!(wp instanceof Artifact)) {
					selected = true;
				} else if (topMostArtifacts.contains(wp)) {
					selected = true;
				}
			} else {
				selected = true;
			}
			if (selected) {
				result.add(child);
			}
		}
		return result;
	}

	/**
	 * This method helps build the artifact descriptor tree correctly
	 * 
	 * @param children
	 * @param unwrap
	 * @param adapterFactory
	 * @return
	 */
	public static List removeSubartifactsFromChildren(final Collection children, boolean unwrap, AdapterFactory adapterFactory) {
		List artifactDescList = new ArrayList();

		// get the artifact list
		//
		for (Iterator iter = children.iterator(); iter.hasNext();) {
			Object child = iter.next();
			if(unwrap) {
				child = TngUtil.unwrap(child);
			}
			if (child instanceof WorkProductDescriptor) {
				WorkProduct wp = ((WorkProductDescriptor) child)
						.getWorkProduct();
				if (wp instanceof Artifact) {
					artifactDescList.add(child);
				}
			}
		}

		if(artifactDescList.isEmpty()) {
			if(children instanceof List) {
				return (List) children;
			}
			else {
				return new ArrayList(children);
			}
		}
		
		// process the artifact list to get the top-most ones
		//
		Set topMostArtifactDescList = new HashSet();
		List artifactDescriptors = new ArrayList(artifactDescList);
		WorkProductDescriptor candidate = null;
		boolean found = false;
		while (!artifactDescList.isEmpty()) {
			
			if (!found)
			{
				candidate = (WorkProductDescriptor) artifactDescList.get(0);
				artifactDescList.remove(0);
			}
			for (Iterator iter = artifactDescList.iterator(); iter.hasNext();) {
				WorkProductDescriptor artifactDesc = (WorkProductDescriptor) iter.next();
				found = false;
				if (ProcessUtil.isContainedBy(candidate, artifactDesc, artifactDescriptors)) {
					iter.remove();
				}
				else if (ProcessUtil.isContainedBy(artifactDesc, candidate, artifactDescriptors)) {
					iter.remove();
					candidate = artifactDesc;

					found = true;
					break;
				}
			}
			if (!found || artifactDescList.isEmpty())
				topMostArtifactDescList.add(candidate);
			else if (artifactDescList.isEmpty())
					topMostArtifactDescList.add(candidate);		
		}

		List result = new ArrayList();
		for (Iterator ci = children.iterator(); ci.hasNext();) {
			Object child = ci.next();
			Object e = unwrap ? TngUtil.unwrap(child) : child;
			boolean selected = false;
			if (e instanceof WorkProductDescriptor) {
				WorkProductDescriptor wpd = ((WorkProductDescriptor) e);
				WorkProduct wp = wpd.getWorkProduct();
				if (!(wp instanceof Artifact)) {
					selected = true;
				} else if (topMostArtifactDescList.contains(wpd)) {
					selected = true;
				}
			} else {
				selected = true;
			}
			if (selected) {
				result.add(child);
			}
		}
		return result;
	}

	public static Activity findActivity(ProcessPackage procPackage) {
		if(procPackage instanceof ProcessComponent) {
			return ((ProcessComponent)procPackage).getProcess();
		}
		for (Iterator iterator = procPackage
				.getProcessElements().iterator(); iterator
				.hasNext();) {
			Object element = iterator.next();
			if (element instanceof Activity) {
				return ((Activity) element);
			}
		}
		return null;
	}	
	
	public static void fixBreakdonwElementOrderRecursively(Activity act) {
		Iterator iter = new AbstractTreeIterator(act) {

			/**
			 * Comment for <code>serialVersionUID</code>
			 */
			private static final long serialVersionUID = 3368261685663354478L;

			protected Iterator getChildren(Object object) {
				ArrayList activities = new ArrayList();
				for (Iterator iterator = ((Activity)object).getBreakdownElements().iterator(); iterator
						.hasNext();) {
					Object element = iterator.next();
					if(element instanceof Activity) {
						activities.add(element);
					}
				}
				return activities.iterator();
			}
			
		};
		while(iter.hasNext()) {
			fixBreakdownElementOrder((Activity)iter.next());
		}
	}

	/**
	 * @param activity
	 */
	public static void fixBreakdownElementOrder(Activity activity) {
		EList list = (EList) activity.getBreakdownElements();
		for (Iterator iter = new ArrayList(list).iterator(); iter.hasNext();) {
			BreakdownElement e = (BreakdownElement) iter.next();
			BreakdownElement succ = e.getPresentedAfter();
			if(succ != null && succ != e) {
				int succId = list.indexOf(succ);
				if(succId != -1) {
					int id = list.indexOf(e);
					if(id != succId - 1) {
						if(id < succId) {
							list.move(succId - 1, id);
						}
						else {
							list.move(succId, id);
						}
					}
					e.setPresentedAfter(null);
				}
			}
		}
	}

	/**
	 * Initializes item provider path of the given activity, the path from top process to the activity
	 * 
	 * @param activity
	 * @param adapterFactory
	 */
	public static void initializeItemProviderPath(Activity activity, AdapterFactory adapterFactory) {
		// get the activity path
		//
		ArrayList actPath = new ArrayList();
		for(activity = activity.getSuperActivities(); activity != null; activity = activity.getSuperActivities()) {
			actPath.add(0, activity);
		}
		for (Iterator iter = actPath.iterator(); iter.hasNext();) {
			Object act = iter.next();
			ITreeItemContentProvider ip = (ITreeItemContentProvider) adapterFactory.adapt(act, ITreeItemContentProvider.class);
			ip.getChildren(act);
		}
	}		

	/**
	 * Check if the given activity or any of its subactivities is a contributor or replacer
	 * 
	 * @param activity
	 * @return
	 */
	public static boolean hasContributorOrReplacer(Activity activity) {
		Iterator iter = new AbstractTreeIterator(activity) {

			/**
			 * Comment for <code>serialVersionUID</code>
			 */
			private static final long serialVersionUID = 0L;

			protected Iterator getChildren(Object object) {
				if(object instanceof Activity) {
					ArrayList children = new ArrayList();
					for (Iterator iterator = ((Activity)object).getBreakdownElements().iterator(); iterator
							.hasNext();) {
						Object element = iterator.next();
						if(element instanceof VariabilityElement) {
							children.add(element);
						}
					}
					return children.iterator();
				}
				return Collections.EMPTY_LIST.iterator();
			}
			
		};
		
		while(iter.hasNext()) {
			VariabilityElement ve = (VariabilityElement) iter.next();
			VariabilityElement base = ve.getVariabilityBasedOnElement();
			VariabilityType vType = ve.getVariabilityType();
			if(base != null && (vType == VariabilityType.CONTRIBUTES_LITERAL || vType == VariabilityType.REPLACES_LITERAL)) {
//				Process proc = TngUtil.getOwningProcess((BreakdownElement) base);
//				if(proc != process) {
//					return true;
//				}
				
				return true;
			}
		}
		
		return false;
	}	
	
	/**
	 * @param target
	 * @return
	 */
	public static boolean isTopProcess(Object target) {
		return target instanceof Process && ((Process)target).eContainer() instanceof ProcessComponent;
	}

	/**
	 * @param wpDescList
	 * @return
	 */
	public static WorkProductDescriptor getWorkProductDescriptor(Collection elements, WorkProduct wp) {
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object e = (Object) iter.next();
			if(e instanceof WorkProductDescriptor) {
				WorkProductDescriptor wpd = ((WorkProductDescriptor)e);
				if(wpd.getWorkProduct() == wp) {
					return wpd;
				}

			}
		}
		return null;
	}

	/**
	 * @param taskDescList
	 * @param task
	 * @return
	 */
	public static TaskDescriptor getTaskDescriptor(Collection elements, Task task) {
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object e = (Object) iter.next();
			if(e instanceof TaskDescriptor) {
				TaskDescriptor td = (TaskDescriptor) e;
				if(td.getTask() == task) {
					return td;
				}
			}
		}
		return null;
	}

	/**
	 * Gets the owning work breakdown element of a work order.
	 * 
	 * @param workOrder
	 *            a work order
	 * @return a work breakdown element that owns the work order or
	 *         <code>null</code>
	 */
	public static WorkBreakdownElement getOwner(WorkOrder workOrder) {
		return AssociationHelper.getSuccessor(workOrder);
	}

	public static ComposedBreakdownElementWrapperItemProvider getComposedWrapper(Object object) {
		while(!(object instanceof ComposedBreakdownElementWrapperItemProvider)
				&& object instanceof IWrapperItemProvider) {
			object = ((IWrapperItemProvider)object).getValue();
		}
		if(object instanceof ComposedBreakdownElementWrapperItemProvider) {
			return (ComposedBreakdownElementWrapperItemProvider) object;
		}
		return null;
	}
}