//------------------------------------------------------------------------------
// 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.process.command;

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

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.edit.IConfigurationApplicator;
import org.eclipse.epf.library.edit.Providers;
import org.eclipse.epf.library.edit.command.BatchCommand;
import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Deliverable;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.Process;
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.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.util.AssociationHelper;


/**
 * @author Phong Nguyen Le - Nov 23, 2005
 * @since 1.0
 */
public final class ProcessCommandUtil {
	public static final EStructuralFeature[] DESCRIPTOR_REFRESHABLE_FEATURES = {
		// UmaPackage.eINSTANCE.getNamedElement_Name(),
		// UmaPackage.eINSTANCE.getDescribableElement_PresentationName(),
		UmaPackage.eINSTANCE.getMethodElement_BriefDescription() 
	};

	public static final EStructuralFeature[] TASK_DESCRIPTOR_REFRESHABLE_FEATURES = {
		UmaPackage.eINSTANCE.getTaskDescriptor_AdditionallyPerformedBy(),
		UmaPackage.eINSTANCE.getTaskDescriptor_MandatoryInput(),
		UmaPackage.eINSTANCE.getTaskDescriptor_OptionalInput(),
		UmaPackage.eINSTANCE.getTaskDescriptor_Output(),
		UmaPackage.eINSTANCE.getTaskDescriptor_PerformedPrimarilyBy(),
		UmaPackage.eINSTANCE.getTaskDescriptor_SelectedSteps() 
	};

	public static final EStructuralFeature[] ROLE_DESCRIPTOR_REFRESHABLE_FEATURES = { 
		UmaPackage.eINSTANCE.getRoleDescriptor_ResponsibleFor() 
	};

//	public static final EStructuralFeature[] WORK_PRODUCT_REFRESHABLE_FEATURES = {
//
//	};

	/**
	 * Creates a refreshable feature map for the given descriptor. A descriptor
	 * feature is considered refreshable if there is a similiar feature in its
	 * linked MethodElement
	 * 
	 * @param descriptor
	 * @return the refreshable feature map for the given descriptor
	 */
	public static Map createRefreshableFeatureMap(Descriptor descriptor, Set excludeFeatures) {
		Map featureMap = new HashMap();
		addToFeatureMap(descriptor, DESCRIPTOR_REFRESHABLE_FEATURES, featureMap, excludeFeatures);
		if (descriptor instanceof TaskDescriptor) {
			addToFeatureMap(descriptor, TASK_DESCRIPTOR_REFRESHABLE_FEATURES,
					featureMap, excludeFeatures);
		} else if (descriptor instanceof RoleDescriptor) {
			addToFeatureMap(descriptor, ROLE_DESCRIPTOR_REFRESHABLE_FEATURES,
					featureMap, excludeFeatures);
		} else if (descriptor instanceof WorkProductDescriptor) {
			WorkProductDescriptor wpd = (WorkProductDescriptor) descriptor;
			EStructuralFeature feature = UmaPackage.eINSTANCE
			.getWorkProductDescriptor_DeliverableParts();
			if (wpd.getWorkProduct() instanceof Deliverable && !excludeFeatures.contains(feature)) {
				featureMap.put(feature, wpd.getDeliverableParts());
			}
		}
		return featureMap;
	}

	private static void addToFeatureMap(EObject eObject,
			EStructuralFeature[] features, Map featureMap, Set excludeFeatures) {
		for (int i = 0; i < features.length; i++) {
			EStructuralFeature feature = features[i];
			if (!excludeFeatures.contains(feature)) {
				Object value = eObject.eGet(feature);
				if (feature.isMany()) {
					value = new ArrayList((Collection) value);
				}
				featureMap.put(feature, value);
			}
		}
	}

	// private static boolean isValidReference(EObject e) {
	// if (e.eIsProxy()) {
	// return false;
	// }
	// if (e instanceof Descriptor) {
	// MethodElement element = ProcessUtil
	// .getAssociatedElement((Descriptor) e);
	// if (element == null || element.eIsProxy()) {
	// return false;
	// }
	// }
	// return true;
	// }

	/**
	 * Clears all attributes. For references, remove only those that are
	 * descriptors which are not linked to any content element.
	 * 
	 * @param descriptor
	 * @return
	 */
	public static Map clearRefreshableFeatures(Descriptor descriptor, Set excludeFeatures) {
		Map featureMap = createRefreshableFeatureMap(descriptor, excludeFeatures);
		for (Iterator iter = featureMap.keySet().iterator(); iter.hasNext();) {
			EStructuralFeature feature = (EStructuralFeature) iter.next();
			if (feature instanceof EAttribute) {
				descriptor.eSet(feature, feature.getDefaultValue());
			} else {
				if (feature.isMany()) {
					// work around to avoid ArrayIndexOutOfBoundsException
					//
					List list = ((List) descriptor.eGet(feature));
					switch (list.size()) {
					case 0:
						break;
					case 1:
						list.remove(0);
						break;
					default:
						list.clear();
					}
				} else {
					descriptor.eSet(feature, feature.getDefaultValue());
				}
				// if(feature.isMany()) {
				// List list = ((List)descriptor.eGet(feature));
				// List elementsToRemove = new ArrayList();
				// for (Iterator iterator = list.iterator(); iterator
				// .hasNext();) {
				// EObject e = (EObject) iterator.next();
				// if(!isValidReference(e)) {
				// elementsToRemove.add(e);
				// }
				// }
				// if(!elementsToRemove.isEmpty()) {
				// list.removeAll(elementsToRemove);
				// System.out
				// .println("ProcessCommandUtil.clearRefreshableFeatures():
				// changed");
				// }
				// }
				// else {
				// EObject obj = (EObject) descriptor.eGet(feature);
				// if(obj != null && obj != feature.getDefaultValue() &&
				// !isValidReference(obj)) {
				// descriptor.eSet(feature, feature.getDefaultValue());
				// System.out
				// .println("ProcessCommandUtil.clearRefreshableFeatures():
				// changed");
				// }
				// }
			}
		}

		return featureMap;
	}

	/**
	 * Clears all the refreshable features of the given descriptor
	 * 
	 * @param descriptor
	 * @param descriptorToOldRefreshableFeaturesMap
	 * @param excludeFeatures features to exclude from refreshing
	 */
	public static boolean clearDescriptor(Descriptor descriptor,
			Map descriptorToOldRefreshableFeaturesMap,
			Set excludeFeatures) {
		if (descriptorToOldRefreshableFeaturesMap != null) {
			// need to clear all the refreshable features of the existing
			// descriptor
			//
			if (!descriptorToOldRefreshableFeaturesMap.containsKey(descriptor)) {
				descriptorToOldRefreshableFeaturesMap
						.put(descriptor, clearRefreshableFeatures(descriptor, excludeFeatures));
				return true;
			}
		}
		return false;
	}
	
	private static boolean isValidDescriptorOf(Object element, MethodConfiguration config, Object descriptor, boolean excludeSuppressed) {		
		if(descriptor instanceof Descriptor) {
			Descriptor desc =  ((Descriptor)descriptor);
			if(excludeSuppressed && desc.getSuppressed().booleanValue()) {
				return false;
			}
			Object elementObj = ProcessUtil.getAssociatedElement(desc);
			elementObj = Providers.getConfigurationApplicator().resolve(elementObj, config);
			return element == elementObj;
		}
		return false;
	}
	
	/**
	 * Checks if the given <code>object</code> is a valid descriptor or descriptor wrapper of the given <code>element</code>
	 * @param element
	 * @param config
	 * @param object
	 * 
	 * @return
	 */
	private static boolean isValidDescriptorOrDescriptorWrapperOf(Object element, MethodConfiguration config, Suppression suppression, Object object) {
		if(object instanceof BreakdownElementWrapperItemProvider) {
			if(suppression.isInSuppressedList((BreakdownElementWrapperItemProvider) object)) {
				return false;
			}
			else {
				return isValidDescriptorOf(element, config, TngUtil.unwrap(object), false);
			}
		}
		return isValidDescriptorOf(element, config, object, true);
	}

	/**
	 * Gets the unsuppressed descriptor from a descriptor list. The descriptor list is usually
	 * the breakdown elements of an activity.
	 * 
	 * @param obj
	 * @param descriptorList
	 * @return
	 */
	public static Object getDescriptor(Object obj, List descriptorList, MethodConfiguration config) {
		return getDescriptor(obj, descriptorList, config, true);
	}
	
	static Object getDescriptor(Object obj, List descriptorList, MethodConfiguration config, boolean excludeSuppressed) {
		int size = descriptorList.size();
		for (int j = 0; j < size; j++) {
			// iterate thru list to see whether a valid descriptor linked with the given object
			// already exists
			//
			Object object = descriptorList.get(j);
			if(isValidDescriptorOf(obj, config, object, excludeSuppressed)) {
				return object;
			}
		}
		return null;
	}
	
	/**
	 * Gets the valid descriptor, either local or inherited, of the given object under the given activity
	 * 
	 * @param obj
	 * @param activity
	 * @return
	 */
	public static Descriptor getValidDescriptor(Object obj, Activity activity, AdapterFactory adapterFactory) {
		Process proc = TngUtil.getOwningProcess(activity);
		MethodConfiguration config = proc.getDefaultContext();
		ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory.adapt(activity, ITreeItemContentProvider.class);
		for (Iterator iter = adapter.getChildren(activity).iterator(); iter.hasNext();) {
			Object child = iter.next();
			if(isValidDescriptorOrDescriptorWrapperOf(obj, config, Suppression.getSuppression(proc), child)) {
				return (Descriptor) TngUtil.unwrap(child);
			}
		}
		return null;
	}
	
	

	/**
	 * Gets the local unsuppressed descriptor of the given role, task, or workProduct.
	 * 
	 * @param obj
	 * @param activity
	 * @return The descriptor of the object, or null if not exist.
	 */
	public static Object getDescriptor(Object obj, Activity activity, MethodConfiguration config) {
		return getDescriptor(obj, activity.getBreakdownElements(), config);
	}

//	/**
//	 * Return true if the descriptor of the given object already exists in the
//	 * breakdown element list of the given activity
//	 * 
//	 * @param obj
//	 * @param activity
//	 * @return
//	 */
//	public static boolean descriptorExists(Object obj, Activity activity) {
//		return (getDescriptor(obj, activity) != null);
//	}

	/**
	 * Create Role descriptor for the responsible role of the given work product
	 * descriptor
	 * 
	 * @param wpDesc
	 * @param activity
	 * @param roleDescriptors
	 * @return
	 */
	public static RoleDescriptor createRoleDescriptor(
			WorkProductDescriptor wpDesc, Activity activity,
			List roleDescriptors, Set descriptorsToRefresh, MethodConfiguration config) {
		if (wpDesc != null) {
			WorkProduct wp = wpDesc.getWorkProduct();
			if (wp != null) {
				if (TngUtil.isContributor(wp)) {
					wp = (WorkProduct) TngUtil.getBase(wp);
				}
				// get responsible role for work product
				Role role = null; //AssociationHelper.getResponsibleRole(wp);
				List roles = AssociationHelper.getResponsibleRoles(wp);
				//FIXME: what if the work product have many responsible roles ???
				if(!roles.isEmpty()) {
					role = (Role) roles.get(0);
				}
				if (role != null) {
					if (TngUtil.isContributor(role)) {
						role = (Role) TngUtil.getBase(role);
					}
					boolean isNewDescriptor = false;
					// check for roledescriptor whether it's present in activity
					// breakdown elements
					RoleDescriptor roleDesc = (RoleDescriptor) getDescriptor(
							role, activity, config);
					if (roleDesc == null) {
						// check for roledescriptor whether it's present in base
						// activity.
						roleDesc = (RoleDescriptor) ProcessCommandUtil.getInheritedDescriptor(
								role, activity, config);
						if (roleDesc == null) {
							// check for roledescriptor whether it's present in
							// list of roledescriptors passed in
							roleDesc = (RoleDescriptor) getDescriptor(role,
									roleDescriptors, config);
							if (roleDesc == null) {
								roleDesc = ProcessUtil.createRoleDescriptor(role);
								roleDescriptors.add(roleDesc);
								isNewDescriptor = true;
							}
						}
					}
					if (!isNewDescriptor && descriptorsToRefresh != null 
							&& roleDesc.getIsSynchronizedWithSource().booleanValue()) {
						descriptorsToRefresh.add(roleDesc);
					}
	
					// this is taken cared of by
					// BSDropCommand#setResponsibleRole()
					//
					// wpDesc.setResponsibleRole(roleDesc);
	
					if(isNewDescriptor) {
						return roleDesc;
					}
				}
			}
		}
		return null;
	}

	/**
	 * Collects work product descriptors for the given
	 * <code>taskDescriptorFeature</code> based on the corresponding feature
	 * in the linked task of the given <code>taskDescriptor</code>
	 * 
	 * @param task the task that the task descriptor is linked to
	 * @param taskDescriptor the task descriptor whose work product descriptors in the given <code>taskDescriptorFeature</code>
	 *        will be collected
	 * @param taskFeature the task feature that is corresponding to the task descriptor feature
	 * @param taskDescriptorFeature the feature of task descriptor that holds references to 
	 *        the work product descriptor to collect
	 * @param activity the activity of descriptors
	 * @param config the selected configuration
	 * @param wpDescriptors
	 * @param wpdToDeliverablePartsMap
	 * @param wpdToDeliverableDescriptorMap
	 * @param descriptorsToRefresh
	 *            ouput that keeps the descriptor features that need to be
	 *            refreshed
	 * @param descriptorToNewFeatureValuesMap
	 *            output that keeps the collected work product descriptors
	 */
	private static void collectWorkProductDescrtiptors(
			Task task,
			TaskDescriptor taskDescriptor, EReference taskFeature,
			EStructuralFeature taskDescriptorFeature,
			MethodConfiguration config, Activity activity, List wpDescriptors,
			Map wpdToDeliverablePartsMap, Map wpdToDeliverableDescriptorMap,
			Set descriptorsToRefresh, Map descriptorToNewFeatureValuesMap) {
		List workProducts = (List) Providers.getConfigurationApplicator()
				.getReference(task, taskFeature, config);
		List list = new ArrayList();
		ProcessCommandUtil.createWorkProductDescriptors(workProducts, list, activity,
				wpDescriptors, wpdToDeliverablePartsMap,
				wpdToDeliverableDescriptorMap, descriptorsToRefresh, config);
		if (!list.isEmpty()) {
			BatchCommand.addFeatureValues(descriptorToNewFeatureValuesMap, taskDescriptor,
					taskDescriptorFeature, list);
		}
	}

	/**
	 * Creates work product descriptors from the given work products for the
	 * given activity if it does not have them already
	 * 
	 * @param workProducts
	 *            WorkProduct list
	 * @param featureValue
	 *            target WorkProductDescriptor list for the given WorkProduct
	 *            list
	 * @param activity
	 * @param wpDescriptors
	 *            newly created work product descriptor (output)
	 */
	static void createWorkProductDescriptors(List workProducts,
			List featureValue, Activity activity, List wpDescriptors,
			Map wpdToDeliverablePartsMap, Map wpdToDeliverableDescriptorMap,
			Set descriptorsToRefresh, MethodConfiguration config) {
		if (workProducts != null) {
			boolean wasEmpty = featureValue.isEmpty();
			for (int j = 0; j < workProducts.size(); j++) {
				WorkProduct wpObj = (WorkProduct) workProducts.get(j);
				if (wpObj != null) {
					if (TngUtil.isContributor(wpObj)) {
						wpObj = (WorkProduct) TngUtil.getBase(wpObj);
					}
					WorkProductDescriptor wpDesc = (WorkProductDescriptor) getDescriptor(wpObj, activity, config);
					if (wpDesc == null) {
	
						// get inherited work product descriptors
						wpDesc = (WorkProductDescriptor) ProcessCommandUtil
								.getInheritedDescriptor(wpObj, activity, config);
						if (wpDesc == null) {
							wpDesc = (WorkProductDescriptor) getDescriptor(wpObj, wpDescriptors, config);
							if (wpDesc == null) {
								wpDesc = ProcessCommandUtil.createWorkProductDescriptor(wpObj,
										config, wpdToDeliverablePartsMap);
								wpDescriptors.add(wpDesc);
	
								// automatic adding to the existing deliverable
								// descriptor in the activity's scope if there
								// is
								// any
								// valid one.
								//
								WorkProductDescriptor descriptor = UserInteractionHelper
										.getDeliverable(activity, wpObj);
								if (descriptor != null) {
									wpdToDeliverableDescriptorMap.put(wpDesc,
											descriptor);
								}
	
							} else {
								if (descriptorsToRefresh != null) {
									descriptorsToRefresh.add(wpDesc);
								}
								if (wpObj instanceof Deliverable
										&& wpdToDeliverablePartsMap != null) {
									ProcessCommandUtil.createDeliverableParts(wpDesc,
											(Deliverable) wpObj, config,
											wpdToDeliverablePartsMap, descriptorsToRefresh);
								}
							}
						}
					}
					if (wasEmpty || !featureValue.contains(wpDesc)) {
						featureValue.add(wpDesc);
					}
				}
			}
		}
	}

	/**
	 * Creates a task descriptor for the given task within the activity if it
	 * does not exist already, and update the roleDescriptors and wpDescriptors lists
	 * associated with this Task descriptor. Caller should add the new task
	 * descriptor and the otherDescriptors into the activity's breakdown element
	 * list.
	 * 
	 * @param task
	 * @param activity
	 * @param roleDescriptors
	 *            List to hold the created role descriptors associated with this
	 *            new task descriptor, no role descriptor will be created if
	 *            roleDescriptors is null
	 * 
	 * @param wpDescriptors
	 *            List to hold the created workproduct descriptors associated
	 *            with this new task descriptor, no workproduct descriptor will
	 *            be created if wpDescriptors is null
	 * 
	 * @param wpdToDeliverableDescriptorMap 
	 *            Map to hold work product descriptor and deliverable descriptor to assign
	 *            the work product descriptor to
	 *             
	 * @return TaskDescriptor or null if the task descriptor for the given task
	 *         already exists, and updated the roleDescriptors and wpDescriptors
	 *         lists
	 */
	public static TaskDescriptor createTaskDescriptor(Task task,
			Activity activity, List roleDescriptors, List wpDescriptors,
			Map wpdToDeliverablePartsMap, Map wpdToDeliverableDescriptorMap,
			Set descriptorsToRefresh, Map descriptorToNewFeatureValuesMap,
			MethodConfiguration config, Set synchFeatures) {
		if (TngUtil.isContributor(task)) {
			task = (Task) TngUtil.getBase(task);
		}
	
		// create task descriptor object
		//
		TaskDescriptor taskDesc = (TaskDescriptor) getDescriptor(
				task, activity, config);
		boolean isNewTaskDescriptor = false;
	
		// if ( taskDesc != null )
		// {
		// return taskDesc;
		// }
		// taskDesc = createTaskDescriptor(task);
	
		if (taskDesc == null) {
			taskDesc = ProcessCommandUtil.createTaskDescriptor(task);
			isNewTaskDescriptor = true;
		} else {
			if (descriptorsToRefresh != null && taskDesc.getIsSynchronizedWithSource().booleanValue()) {
				descriptorsToRefresh.add(taskDesc);
			}
		}
	
		IConfigurationApplicator configApplicator = Providers
				.getConfigurationApplicator();
	
		if (isNewTaskDescriptor) {
			// add all task steps to TaskDescriptor step selection
			//
			List steps = (List) configApplicator.getReference(task
					.getPresentation(), task, UmaPackage.eINSTANCE
					.getContentDescription_Sections(), config);
			taskDesc.getSelectedSteps().addAll(steps);
			
		}
	
		// moved this code to BSDropCommand#execute() to support undo and
		// progress monitor
		//
		// else {
		// for (Iterator iter = steps.iterator(); iter.hasNext();) {
		// Object step = iter.next();
		// if (!taskDesc.getSelectedSteps().contains(step)) {
		// taskDesc.getSelectedSteps().add(step);
		// }
		// }
		// }
	
		if (roleDescriptors != null) {
			// get/create role descriptor for primary performer
			//
			EReference ref = UmaPackage.eINSTANCE.getTask_PerformedBy();
			Role role = synchFeatures.contains(ref) ? (Role) configApplicator.getReference(task,
					ref, config) : null;
			if (role != null) {
				// if (TngUtil.isContributor(role)) {
				// role = (Role) TngUtil.getBase(role);
				// }
	
				// check for local descriptor
				RoleDescriptor primaryRoleDesc = (RoleDescriptor) getDescriptor(
						role, activity, config);
				boolean isNewRoleDescriptor = false;
				if (primaryRoleDesc == null) {
					// check for inherited descriptor
					primaryRoleDesc = (RoleDescriptor) ProcessCommandUtil.getInheritedDescriptor(
							role, activity, config);
					if (primaryRoleDesc == null) {
						// check for descriptor in passed in descriptor list
						primaryRoleDesc = (RoleDescriptor) getDescriptor(role,
								roleDescriptors, config);
						if (primaryRoleDesc == null) {
							primaryRoleDesc = ProcessUtil.createRoleDescriptor(role);
							isNewRoleDescriptor = true;
							roleDescriptors.add(primaryRoleDesc);
						}
					}
				}
				if (descriptorsToRefresh != null && !isNewRoleDescriptor
						&& primaryRoleDesc.getIsSynchronizedWithSource().booleanValue()) {
					descriptorsToRefresh.add(primaryRoleDesc);
				}
				if (isNewTaskDescriptor && isNewRoleDescriptor) {
					taskDesc.setPerformedPrimarilyBy(primaryRoleDesc);
				} else {
					BatchCommand.addFeatureValue(descriptorToNewFeatureValuesMap, taskDesc,
							UmaPackage.eINSTANCE
									.getTaskDescriptor_PerformedPrimarilyBy(),
							primaryRoleDesc);
				}
			}
	
			// get/create role descriptors for additional performing roles
			//
			ref = UmaPackage.eINSTANCE.getTask_AdditionallyPerformedBy();			
			List additionalPerformers = synchFeatures.contains(ref) ? (List) configApplicator.getReference(
					task, ref, config) : null;
			if (additionalPerformers != null) {
				for (int j = 0; j < additionalPerformers.size(); j++) {
					Role roleObj = (Role) additionalPerformers.get(j);
					// check for local descriptor
					RoleDescriptor roleDesc = (RoleDescriptor) getDescriptor(
							roleObj, activity, config);
					boolean isNewRoleDescriptor = false;
					if (roleDesc == null) {
						// check for inherited descriptor
						roleDesc = (RoleDescriptor) ProcessCommandUtil.getInheritedDescriptor(
								roleObj, activity, config);
						if (roleDesc == null) {
							roleDesc = (RoleDescriptor) getDescriptor(roleObj,
									roleDescriptors, config);
							if (roleDesc == null) {
								roleDesc = ProcessUtil.createRoleDescriptor(roleObj);
								isNewRoleDescriptor = true;
								roleDescriptors.add(roleDesc);
							}
						}
					}
					if (descriptorsToRefresh != null && !isNewRoleDescriptor
							&& roleDesc.getIsSynchronizedWithSource().booleanValue()) {
						descriptorsToRefresh.add(roleDesc);
					}
					if (isNewTaskDescriptor && isNewRoleDescriptor) {
						taskDesc.getAdditionallyPerformedBy().add(roleDesc);
					} else {
						BatchCommand.addFeatureValue(
								descriptorToNewFeatureValuesMap,
								taskDesc,
								UmaPackage.eINSTANCE
										.getTaskDescriptor_AdditionallyPerformedBy(),
								roleDesc);
	
					}
				}
			}
		}
	
		if (wpDescriptors != null) {
			if (!isNewTaskDescriptor && !synchFeatures.contains(UmaPackage.eINSTANCE.getDeliverable_DeliveredWorkProducts())) {
				wpdToDeliverablePartsMap = null;
			}
			
			// create work product descriptor for input workproducts
			//
			if (isNewTaskDescriptor || synchFeatures.contains(UmaPackage.eINSTANCE.getTask_MandatoryInput())) {
				collectWorkProductDescrtiptors(task, taskDesc, UmaPackage.eINSTANCE
						.getTask_MandatoryInput(), UmaPackage.eINSTANCE
						.getTaskDescriptor_MandatoryInput(), config, activity,
						wpDescriptors, wpdToDeliverablePartsMap,
						wpdToDeliverableDescriptorMap, descriptorsToRefresh,
						descriptorToNewFeatureValuesMap);
			}
			if (isNewTaskDescriptor || synchFeatures.contains(UmaPackage.eINSTANCE.getTask_OptionalInput())) {
				collectWorkProductDescrtiptors(task, taskDesc, UmaPackage.eINSTANCE
						.getTask_OptionalInput(), UmaPackage.eINSTANCE
						.getTaskDescriptor_OptionalInput(), config, activity,
						wpDescriptors, wpdToDeliverablePartsMap,
						wpdToDeliverableDescriptorMap, descriptorsToRefresh,
						descriptorToNewFeatureValuesMap);
			}
	
			// create work product descriptor for output workproducts
			//
			if (isNewTaskDescriptor || synchFeatures.contains(UmaPackage.eINSTANCE.getTask_Output())) {
				collectWorkProductDescrtiptors(task, taskDesc, UmaPackage.eINSTANCE
						.getTask_Output(), UmaPackage.eINSTANCE
						.getTaskDescriptor_Output(), config, activity,
						wpDescriptors, wpdToDeliverablePartsMap,
						wpdToDeliverableDescriptorMap, descriptorsToRefresh,
						descriptorToNewFeatureValuesMap);
			}
		}
	
		if (isNewTaskDescriptor) {
			return taskDesc;
		}
	
		return null;
	}

	private static TaskDescriptor createTaskDescriptor(Task task) {
		TaskDescriptor taskDesc = UmaFactory.eINSTANCE.createTaskDescriptor();
		taskDesc.setTask(task);
		taskDesc.setName(task.getName());
		taskDesc.setPresentationName(StrUtil
				.isBlank(task.getPresentationName()) ? task.getName() : task
				.getPresentationName());
		// taskDesc.setBriefDescription(task.getBriefDescription());
		return taskDesc;
	}

	/**
	 * Creates deliverable parts for the given work product descriptor from the
	 * deliverable work products of the given deliverable add put them in
	 * <code>wpDescToDeliverableParts</code>
	 * 
	 * @param wpd
	 * @param deliverable
	 * @param wpDescToDeliverableParts
	 *            (output) map of work product descriptor to its newly created
	 *            deliverable parts
	 */
	public static void createDeliverableParts(WorkProductDescriptor wpd,
			Deliverable deliverable, MethodConfiguration config,
			Map wpDescToDeliverableParts, Set descriptorsToRefresh) {
		IConfigurationApplicator configApplicator = Providers
				.getConfigurationApplicator();
	
		List deliveredWPs = (List) configApplicator.getReference(deliverable,
				UmaPackage.eINSTANCE.getDeliverable_DeliveredWorkProducts(),
				config);
		List parts = new ArrayList();
		if (wpd.getDeliverableParts().isEmpty()) {
			for (Iterator iter = deliveredWPs.iterator(); iter.hasNext();) {
				parts.add(ProcessCommandUtil.createWorkProductDescriptor(
						(WorkProduct) iter.next(), config,
						wpDescToDeliverableParts));
			}
		} else {
			for (Iterator iter = deliveredWPs.iterator(); iter.hasNext();) {
				WorkProduct workProduct = (WorkProduct) iter.next();
				WorkProductDescriptor desc = (WorkProductDescriptor) getDescriptor(workProduct, wpd.getDeliverableParts(), config);
				if (desc == null) {
					desc = ProcessCommandUtil.createWorkProductDescriptor(
							workProduct, config, wpDescToDeliverableParts);
				} else {
					if(descriptorsToRefresh != null) {
						descriptorsToRefresh.add(desc);
					}
					if (workProduct instanceof Deliverable) {
						createDeliverableParts(desc, (Deliverable) workProduct,
								config, wpDescToDeliverableParts, descriptorsToRefresh);
					}
				}
				parts.add(desc);
			}
		}
		if (!parts.isEmpty()) {
			wpDescToDeliverableParts.put(wpd, parts);
		}
	}

	/**
	 * Creates work product descriptor for the given work product
	 * 
	 * @param wp
	 * @param config
	 * @param wpDescToDeliverableParts
	 *            (output) map of work product descriptor to its newly created
	 *            deliverable parts
	 * @return new WorkProductDescriptor or <code>null</code> if the
	 *         descriptor for the given work product already exists
	 */
	public static WorkProductDescriptor createWorkProductDescriptor(
			WorkProduct wp, MethodConfiguration config,
			Map wpDescToDeliverableParts) {
		WorkProductDescriptor wpd = ProcessUtil.createWorkProductDescriptor(wp);
		if (wp instanceof Deliverable && wpDescToDeliverableParts != null) {
			createDeliverableParts(wpd, (Deliverable) wp, config,
					wpDescToDeliverableParts, null);
		}
		return wpd;
	}

	/**
	 * Get inhertied descriptor for the given role, task or workProduct. Unlike local descriptor, an inherited 
	 * descriptor that is externally suppressed is considered valid.
	 * 
	 * @param obj
	 * @param activity
	 * @return descriptor of the object, null if not exists
	 */
	public static Object getInheritedDescriptor(Object obj, Activity activity, MethodConfiguration config) {
		for (VariabilityType variabilityType = activity.getVariabilityType();
			variabilityType == VariabilityType.EXTENDS_LITERAL || variabilityType == VariabilityType.LOCAL_CONTRIBUTION_LITERAL;
			variabilityType = activity.getVariabilityType()) {
			VariabilityElement element = activity.getVariabilityBasedOnElement();
	
			if (element instanceof Activity) {
				Activity baseActivity = (Activity) element;
				Object desc = getDescriptor(obj, baseActivity.getBreakdownElements(), config, false);
				if(desc != null) {
					return desc;
				}
				activity = baseActivity;
			}
			else {
				break;
			}
		}
	
		return null;
	}
	
	/**
	 * Get the map of task to features that contain the work product 
	 * (input or output of the task)
	 * 
	 * @param tasks
	 * @param wp
	 * @return Map of task to features that contain the work product
	 */
	public static Map getFeaturesMap(List tasks, WorkProduct wp, MethodConfiguration config) {
		Map featuresMap = new HashMap();
		EReference[] taskFeatures = {
				UmaPackage.eINSTANCE.getTask_MandatoryInput(),
				UmaPackage.eINSTANCE.getTask_OptionalInput(),
				UmaPackage.eINSTANCE.getTask_Output()
		};
		for (int i = tasks.size() - 1; i > -1; i--) {
			Task task = (Task) tasks.get(i);
			for (int j = 0; j < taskFeatures.length; j++) {
				EReference feature = taskFeatures[j];
				Object value = Providers.getConfigurationApplicator().getReference(task, feature, config);
				if((feature.isMany() && ((List)value).contains(wp)) ||
						value == wp) 
				{
					Collection features = (Collection) featuresMap.get(task);
					if(features == null) {
						features = new ArrayList();	
						featuresMap.put(task, features);
					}
					features.add(feature);
				}
			}
		}
		return featuresMap;
	}
}
