//------------------------------------------------------------------------------
// 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.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.command.AbstractCommand;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.epf.library.edit.IConfigurationApplicator;
import org.eclipse.epf.library.edit.LibraryEditPlugin;
import org.eclipse.epf.library.edit.Providers;
import org.eclipse.epf.library.edit.command.BatchCommand;
import org.eclipse.epf.library.edit.command.INestedCommandProvider;
import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
import org.eclipse.epf.library.edit.command.NestedCommandExcecutor;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.ExtensionManager;
import org.eclipse.epf.library.edit.util.IRunnableWithProgress;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
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.UmaPackage;
import org.eclipse.epf.uma.WorkProductDescriptor;

/**
 * Abstract base DropCommand class for breakdown structure editor
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public abstract class BSDropCommand extends AbstractCommand implements
		IResourceAwareCommand {
	public static final Set<EStructuralFeature> DEFAULT_SYNCH_FEATURES = Collections.unmodifiableSet(new HashSet<EStructuralFeature>(Arrays.asList(
			new EStructuralFeature[] {
					UmaPackage.eINSTANCE.getNamedElement_Name(),
					UmaPackage.eINSTANCE.getMethodElement_BriefDescription(),
					UmaPackage.eINSTANCE.getMethodElement_PresentationName(),
					UmaPackage.eINSTANCE.getTask_OptionalInput(),
					UmaPackage.eINSTANCE.getTask_MandatoryInput(),
					UmaPackage.eINSTANCE.getTask_Output(),
					UmaPackage.eINSTANCE.getTask_Steps(),				
					UmaPackage.eINSTANCE.getTask_PerformedBy(),
					UmaPackage.eINSTANCE.getTask_AdditionallyPerformedBy(),
					UmaPackage.eINSTANCE.getRole_ResponsibleFor(),
					UmaPackage.eINSTANCE.getArtifact_ContainedArtifacts(),
					UmaPackage.eINSTANCE.getDeliverable_DeliveredWorkProducts()
			}
	)));
	
	/**
	 * Map of linked element's feature to descriptor's feature
	 */
	public static final Map<EStructuralFeature, EStructuralFeature> FEATURE_MAP = new HashMap<EStructuralFeature, EStructuralFeature>();
	static {
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getNamedElement_Name(), UmaPackage.eINSTANCE.getNamedElement_Name());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getMethodElement_BriefDescription(), UmaPackage.eINSTANCE.getMethodElement_BriefDescription());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getMethodElement_PresentationName(), UmaPackage.eINSTANCE.getMethodElement_PresentationName());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getTask_OptionalInput(), UmaPackage.eINSTANCE.getTaskDescriptor_OptionalInput());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getTask_MandatoryInput(), UmaPackage.eINSTANCE.getTaskDescriptor_MandatoryInput());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getTask_Output(), UmaPackage.eINSTANCE.getTaskDescriptor_Output());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getRole_ResponsibleFor(), UmaPackage.eINSTANCE.getRoleDescriptor_ResponsibleFor());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getDeliverable_DeliveredWorkProducts(), UmaPackage.eINSTANCE.getWorkProductDescriptor_DeliverableParts());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getTask_Steps(), UmaPackage.eINSTANCE.getTaskDescriptor_SelectedSteps());
//		FEATURE_MAP.put(UmaPackage.eINSTANCE.getEstimatedMethodElement_Estimate(), UmaPackage.eINSTANCE.getEstimatedMethodElement_Estimate());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getTask_AdditionallyPerformedBy(), UmaPackage.eINSTANCE.getTaskDescriptor_AdditionallyPerformedBy());
		FEATURE_MAP.put(UmaPackage.eINSTANCE.getTask_PerformedBy(), UmaPackage.eINSTANCE.getTaskDescriptor_PerformedPrimarilyBy());
	}

	protected Activity activity;

	protected List<Object> dropElements;
	
	protected List<Object> unwrappedDropElements;

	private Set<Resource> modifiedResources;

	protected List<Object> elementsToAddToDefaultConfig;

	protected Set<Object> addedObjects;

	private Process process;

	private boolean addedToDefaultConfig = false;

	protected boolean synchronize = false;

	protected ArrayList<TaskDescriptor> taskDescList;

	protected ArrayList<Descriptor> taskDescriptorsToUpdate;

//	protected Set descriptorsToRefresh;

	/**
	 * Map of descriptor to old refreshable feature map
	 */
	private Map<Descriptor, Map<?, ?>> descriptorToOldRefreshableFeaturesMap;

	/**
	 * Map of descriptor to map of feature to new values
	 */
//	protected Map descriptorToNewFeatureValuesMap;
//	private HashMap descriptorToOldFeatureValuesMap;	
	protected DescriptorUpdateBatchCommand batchCommand;

//	private HashMap wpdToOldResponsibleRoleMap;

	/**
	 * Map of TaskDescriptor to list of newly added steps
	 */
	private Map taskDescToNewStepsMap;

	private Map taskDescToOldEstimateMap;
	
	protected boolean canceled;

	private MethodConfiguration config;

	protected Set synchFeatures = DEFAULT_SYNCH_FEATURES;

	private BatchCommand refreshResponsibleForCommand;

	protected boolean executed;

//	protected Object UIContext;
	
	protected boolean runAsJob;
	
	private IProgressMonitor monitor;

	private int workedUnits;

	private NestedCommandExcecutor nestedCommandExcecutor;
	
	/**
	 * @param activity
	 *            the activity that the given elements are dropped on
	 * @param dropElements
	 *            the elements to drop on the given activity
	 */
	public BSDropCommand(Activity activity, List<Object> dropElements) {
		this(activity, dropElements, null, null, false);
	}

	/**
	 * @param synch
	 *            if true, the command will clean the content and relationships
	 *            of existing descriptors and refresh them with the linked
	 *            MethodElement
	 */
	public BSDropCommand(Activity activity, List<Object> dropElements, boolean synch) {
		this(activity, dropElements, null, null, synch);
	}

	/**
	 * Synchronize the given content elements to its TaskDescriptors in the
	 * given activity using the given MethodConfiguration and list of
	 * synchronizable features.
	 * 
	 * @param activity
	 * @param dropElements
	 *            the elements to synchronize
	 * @param config
	 * @param synchFeatures
	 *            the synchronizable features, if <code>null</code> the DEFAULT_SYNCH_FEATURES will be used.
	 */
	public BSDropCommand(Activity activity, List<Object> dropElements,
			MethodConfiguration config, Set synchFeatures) {
		this(activity, dropElements, config, synchFeatures, true);
	}
	
	public BSDropCommand(Activity activity, List<Object> dropElements,
			MethodConfiguration config, Set synchFeatures, boolean synch) {
		super();
		this.activity = activity;
		process = TngUtil.getOwningProcess(activity);
		this.synchronize = synch;
		this.config = config;
		if (synchFeatures == null) {
			this.synchFeatures = DEFAULT_SYNCH_FEATURES;
		}
		else {
			this.synchFeatures = synchFeatures;
		}
		
		this.dropElements = dropElements;
		nestedCommandExcecutor = createNestedCommandExcecutor();
	}
	
	protected NestedCommandExcecutor createNestedCommandExcecutor() {
		return new NestedCommandExcecutor(this) {
			@Override
			public void executeNestedCommands() {
				if(taskDescList != null && !taskDescList.isEmpty()) {
					List nestedCommandProviders = ExtensionManager
					.getNestedCommandProviders();
					if (!nestedCommandProviders.isEmpty()) {
						for (Iterator iter = nestedCommandProviders.iterator(); iter
						.hasNext();) {
							INestedCommandProvider cmdProvider = (INestedCommandProvider) iter
							.next();
							try {
								Command cmd = cmdProvider.createRelatedObjects(
										taskDescList, BSDropCommand.this);
								if (cmd != null && cmd.canExecute()) {
									cmd.execute();
									getNestedCommands().add(cmd);
								}
							} catch (Exception e) {
								LibraryEditPlugin.getDefault().getLogger()
								.logError(e);
							}
						}
					}
				}

				super.executeNestedCommands();
			}
		};
	}
	
	protected IProgressMonitor getProgressMonitor() {
		if(monitor == null) {
			monitor = new NullProgressMonitor();
		}
		return monitor;
	}
	
	protected void prepareDropElements() {		
		ArrayList<Object> elements = new ArrayList<Object>();
		getMethodConfiguration();
		unwrappedDropElements = new ArrayList<Object>();
		for (Object o : dropElements) {
			Object element = TngUtil.unwrap(o);
			element = Providers.getConfigurationApplicator().resolve(element, config);
			if (!elements.contains(element)
					&& !(element instanceof EObject && ((EObject) element)
							.eIsProxy())) {				
				elements.add(element);
				unwrappedDropElements.add(o);
			}
		}
		dropElements = elements;
	}
	
//	/**
//	 * Sets UI context for this command, this can be a Shell object
//	 * @param UIContext
//	 */
//	public void setUIContext(Object UIContext) {
//		this.UIContext = UIContext;
//	}

	public MethodConfiguration getMethodConfiguration() {
		if(config == null) {
			config = TngUtil.getOwningProcess(activity).getDefaultContext();
		}
		return config;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.AbstractCommand#dispose()
	 */
	public void dispose() {
		if (dropElements != null) {
			dropElements.clear();
		}
		if(unwrappedDropElements != null) {
			unwrappedDropElements.clear();
		}
		if (modifiedResources != null) {
			modifiedResources.clear();
		}
		if (elementsToAddToDefaultConfig != null) {
			elementsToAddToDefaultConfig.clear();
		}
		if (addedObjects != null) {
			addedObjects.clear();
		}
		if (descriptorToOldRefreshableFeaturesMap != null) {
			descriptorToOldRefreshableFeaturesMap.clear();
		}
		if (taskDescList != null) {
			taskDescList.clear();
		}
		if (taskDescToNewStepsMap != null) {
			taskDescToNewStepsMap.clear();
		}
		if (taskDescToOldEstimateMap != null) {
			taskDescToOldEstimateMap.clear();
		}
		if (refreshResponsibleForCommand != null) {
			refreshResponsibleForCommand.dispose();
		}
		if (taskDescriptorsToUpdate != null) {
			taskDescriptorsToUpdate.clear();
		}
		if(batchCommand != null) {
			batchCommand.dispose();
		}
		activity = process = null;
		if(nestedCommandExcecutor != null) {
			nestedCommandExcecutor.dispose();
		}
		super.dispose();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.command.IResourceAwareCommand#getModifiedResources()
	 */
	public Collection<Resource> getModifiedResources() {
		if (modifiedResources == null) {
			modifiedResources = new HashSet<Resource>();
			if (activity.eResource() != null) {
				modifiedResources.add(activity.eResource());
			}
		}
		
		modifiedResources.addAll(nestedCommandExcecutor.getModifiedResources());

		return modifiedResources;
	}

	/**
	 * Clears all the refreshable features of the given descriptor
	 * 
	 * @param descriptor
	 */
	private boolean clearDescriptor(Descriptor descriptor) {
		Set excludeSynchFeatures = new HashSet(DEFAULT_SYNCH_FEATURES);
		excludeSynchFeatures.removeAll(synchFeatures);
		Set excludeFeatures;
		if (excludeSynchFeatures.isEmpty()) {
			excludeFeatures = excludeSynchFeatures;
		}
		else {
			excludeFeatures = new HashSet();
			for (Iterator iter = excludeSynchFeatures.iterator(); iter.hasNext();) {
				EStructuralFeature feature = getDescriptorFeature((EStructuralFeature) iter.next());
				if(feature != null) {
					excludeFeatures.add(feature);
				}
			}
		}
		boolean ret = ProcessCommandUtil.clearDescriptor(descriptor,
				descriptorToOldRefreshableFeaturesMap, excludeFeatures);
		if (ret && descriptor instanceof TaskDescriptor) {
			if (taskDescriptorsToUpdate == null) {
				taskDescriptorsToUpdate = new ArrayList<Descriptor>();
			}
			taskDescriptorsToUpdate.add(descriptor);
		}
		return ret;
	}

	/**
	 * @param feature
	 * @return
	 */
	private static EStructuralFeature getDescriptorFeature(EStructuralFeature linkedElementFeature) {
		return (EStructuralFeature) FEATURE_MAP.get(linkedElementFeature);
	}
	
	protected boolean preExecute() {
		prepareDropElements();
		
		boolean b = !dropElements.isEmpty();
		if (b) {
//			descriptorToNewFeatureValuesMap = new HashMap();
			batchCommand = new DescriptorUpdateBatchCommand(false, synchFeatures, config); //TODO: why clear must be false ???

//			if (synchronize) {
//				descriptorsToRefresh = new HashSet();
//			}
		}
		return b;
	}
	
	protected boolean collectElementsToAddToDefaultConfig() {
		if (elementsToAddToDefaultConfig == null) {
			elementsToAddToDefaultConfig = new ArrayList<Object>();
			for (Iterator iter = dropElements.iterator(); iter.hasNext();) {
				Object element = iter.next();
				switch (UserInteractionHelper.checkAgainstDefaultConfiguration(
						process, element)) {
				case 0:
					iter.remove();
					break;
				case 2:
					elementsToAddToDefaultConfig.add(element);
					break;
				case -1:
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * Adds elements to the default configuration
	 * 
	 * @return true if default configuration has been modified, false otherwise
	 */
	private boolean addToDefaultConfiguration() {
		if (!addedToDefaultConfig && elementsToAddToDefaultConfig != null && !elementsToAddToDefaultConfig.isEmpty()) {
			if(addedObjects == null) {
				addedObjects = new HashSet();
			}
			else {
				addedObjects.clear();
			}
			for (Iterator iter = elementsToAddToDefaultConfig.iterator(); iter
			.hasNext();) {
				EObject element = (EObject) iter.next();
				ProcessUtil.addToDefaultConfiguration(process, element,
						addedObjects);
			}
			if (!addedObjects.isEmpty()) {
				getModifiedResources().add(
						process.getDefaultContext().eResource());
				return true;
			}
			addedToDefaultConfig = true;
		}
		return false;
	}
	
	protected int getTotalWork() {
		return 20;
	}
	
	protected void worked(int unitsOfWork) {
		monitor.worked(unitsOfWork);
		workedUnits = workedUnits + unitsOfWork;
	}
	
	protected int getRemainingWork() {
		int remaining = getTotalWork() - workedUnits;
		if(remaining < 0) {
			remaining = 0;
		}
		return remaining;
	}

	protected boolean updateDefaultConfigurationNeeded() {
		return !synchronize;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.Command#execute()
	 */
	public void execute() {		
		// BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
		//			
		// public void run() {
		// canceled = !addToDefaultConfiguration();
		// }
		//			
		// });
		//		
		// //TODO: This caused NullPointerException or ThreadAccessError when
		// showing selection dialog is needed
		// //
		// IRunnableWithProgress runnable = new IRunnableWithProgress() {
		//
		// public void run(IProgressMonitor monitor) throws
		// InvocationTargetException, InterruptedException {
		// canceled = !preExecute();
		// }
		//			
		// };
		// UserInteractionHelper.runWithProgress(runnable, null);
		//		
		// if(!canceled) {
		// BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
		//				
		// public void run() {
		// redo();
		// }
		//				
		// });
		// }

//		BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
//
//			public void run() {
//				if ((!synchronize && addToDefaultConfiguration()) && preExecute()) {
//					redo();
//				}
//			}
//
//		});
		
		if(updateDefaultConfigurationNeeded()) {
			if(!collectElementsToAddToDefaultConfig()) {
				return;
			}
		}
		
		final String taskName = (label == null ? "" : label); //$NON-NLS-1$
		IRunnableWithProgress runnable = new IRunnableWithProgress() {

			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
				try {
					monitor.beginTask(taskName, getTotalWork());
					BSDropCommand.this.monitor = monitor;
					worked(getRemainingWork() / 3);
					
					// this must be called before preExecute() to add required elements to configuration
					// so the command can realize data correctly
					//
					addToDefaultConfiguration();
					worked(getRemainingWork() / 3);
					
					if (preExecute()) {
						worked(getRemainingWork() / 3);
						redo();
					}
				}
				finally {
					monitor.done();
				}
			}
			
		};
		if(runAsJob) {
			UserInteractionHelper.runAsJob(runnable, taskName);
		}
		else {
//			UserInteractionHelper.runInUI(runnable, (Shell)null);
			UserInteractionHelper.runWithProgress(runnable, null);
		}
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.Command#redo()
	 */
	public void redo() {
		try {
			// add elements to the default configuration if needed
			//
			addToDefaultConfiguration();
			
			doExecute();
			updateDescriptors();
			
			long time = 0;
			if(TngUtil.DEBUG) {
				time = System.currentTimeMillis();
			}
			nestedCommandExcecutor.executeNestedCommands();
			if(TngUtil.DEBUG) {
				System.out.println("BSDropCommand.redo(): executeNestedCommands(). " + (System.currentTimeMillis() - time));
			}
			
			executed = true;
		}
		catch(RuntimeException e) {
			if(TngUtil.DEBUG) {
				e.printStackTrace();
			}
			LibraryEditPlugin.getDefault().getLogger().logError(e);
			throw e;
		}
	}

	/**
	 * Updates descriptors
	 */
	protected void updateDescriptors() {
		if (synchronize) {
			clearDescriptors();
		}

		// update new values;
		//
		batchCommand.execute();
		
		updateTaskDescriptors();

		setResponsibleRoles();
	}

//	/**
//	 * @param desc
//	 * @param feature
//	 * @param value
//	 */
//	protected void saveOldFeatureValue(Descriptor desc,
//			EStructuralFeature feature) {
//		if (descriptorToOldFeatureValuesMap == null) {
//			descriptorToOldFeatureValuesMap = new HashMap();
//		}
//		Object value = desc.eGet(feature);
//		if(feature.isMany()) {
//			value = new ArrayList((List)value);
//		}
//		Map featureMap = (Map) descriptorToOldFeatureValuesMap.get(desc);
//		if (featureMap == null) {
//			featureMap = new HashMap();
//			descriptorToOldFeatureValuesMap.put(desc, featureMap);
//		}
//		featureMap.put(feature, value);
//	}

	protected void undoUpdateDescriptors() {
		undoSetResponsibleRole();

		undoUpdateTaskDescriptors();

		// restore old values
		//
		batchCommand.undo();

		// restore value for refreshable features that had been cleared
		//
		if (synchronize) {
			undoClearDescriptors();
		}
	}

	/**
	 * 
	 */
	private void clearDescriptors() {
		if (descriptorToOldRefreshableFeaturesMap == null) {
			descriptorToOldRefreshableFeaturesMap = new HashMap();
			if (!batchCommand.getDescriptorsToRefresh().isEmpty()) {
				for (Iterator iter = batchCommand.getDescriptorsToRefresh().iterator(); iter
						.hasNext();) {
					clearDescriptor((Descriptor) iter.next());
				}
				// descriptorsToRefresh.clear();
			}
		}
	}

	/**
	 * Updates affected task descriptors with new data from method content
	 */
	private void updateTaskDescriptors() {
		if (taskDescriptorsToUpdate != null) {
			// refresh steps from the associated task
			//
			if(synchFeatures.contains(UmaPackage.eINSTANCE.getTask_Steps())) {
				if (taskDescToNewStepsMap == null) {
					taskDescToNewStepsMap = new HashMap();
				}
				IConfigurationApplicator configApplicator = Providers
				.getConfigurationApplicator();
				for (Iterator iter = taskDescriptorsToUpdate.iterator(); iter
				.hasNext();) {
					TaskDescriptor taskDesc = (TaskDescriptor) iter.next();
					Task task = taskDesc.getTask();
					if (task != null && !((EObject) task).eIsProxy()) {
						List steps = (List) configApplicator.getReference(task
								.getPresentation(), task, UmaPackage.eINSTANCE
								.getContentDescription_Sections(), config);
						
						// add those steps to TaskDescriptor if they are not there
						// yet.
						//
						ArrayList newSteps = new ArrayList();
						taskDesc.getSelectedSteps().retainAll(steps);
						for (Iterator iter1 = steps.iterator(); iter1.hasNext();) {
							Object step = iter1.next();
							if (!taskDesc.getSelectedSteps().contains(step)) {
								newSteps.add(step);
							}
						}
						if (!newSteps.isEmpty()) {
							taskDesc.getSelectedSteps().addAll(newSteps);
							taskDescToNewStepsMap.put(taskDesc, newSteps);
//							System.out
//							.println("BSDropCommand.updateTaskDescriptors(): changed");
						}
					}
				}
			}
			
		}
	}

	private void undoUpdateTaskDescriptors() {
		if (taskDescToNewStepsMap != null) {
			for (Iterator iter = taskDescToNewStepsMap.entrySet().iterator(); iter
					.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				TaskDescriptor taskDesc = (TaskDescriptor) entry.getKey();
				taskDesc.getSelectedSteps().removeAll(
						(Collection) entry.getValue());
			}
		}
	}

	/**
	 * Go thru all the work product descriptors of this activity and set the
	 * responsible role for them if there is any
	 */
	private void setResponsibleRoles() {
		if(!synchFeatures.contains(UmaPackage.eINSTANCE.getRole_ResponsibleFor())) {
			return;
		}
		
		if(refreshResponsibleForCommand != null) {
			refreshResponsibleForCommand.dispose();
		}
		refreshResponsibleForCommand = new BatchCommand(true);
 
		List brElements = activity.getBreakdownElements();
		List wpDescList = new ArrayList();
		List roleDescriptors = new ArrayList();
		for (Iterator itor = brElements.iterator(); itor.hasNext();) {
			Object obj = itor.next();
			if (obj instanceof WorkProductDescriptor) {
				wpDescList.add(obj);
			} else if (obj instanceof RoleDescriptor) {
				roleDescriptors.add(obj);
			}
		}

		for (Iterator itor = roleDescriptors.iterator(); itor.hasNext();) {
			RoleDescriptor roleDesc = (RoleDescriptor) itor.next();
			Role role = roleDesc.getRole();
			if (role != null) {				
				List responsibleWorkProducts = (List) Providers.getConfigurationApplicator().getReference(role, UmaPackage.eINSTANCE.getRole_ResponsibleFor(), config);
				List responsibleWPDList = new ArrayList();
				for (int j = wpDescList.size() - 1; j > -1; j--) {
					WorkProductDescriptor wpDesc = (WorkProductDescriptor) wpDescList
							.get(j);
//					RoleDescriptor responsibleRoleDesc = AssociationHelper.getResponsibleRoleDescriptor(wpDesc);
//					if (responsibleWorkProducts.contains(wpDesc
//							.getWorkProduct())
//							&&  responsibleRoleDesc != roleDesc) {
//						wpdToOldResponsibleRoleMap.put(wpDesc, responsibleRoleDesc);
////						wpDesc.setResponsibleRole(roleDesc);
//						roleDesc.getResponsibleFor().add(wpDesc);
//					}
					
					if(responsibleWorkProducts.contains(wpDesc.getWorkProduct())) {
						responsibleWPDList.add(wpDesc);
					}
				}				
				if(!roleDesc.getResponsibleFor().equals(responsibleWPDList)) {
					refreshResponsibleForCommand.addFeatureValues(roleDesc, UmaPackage.eINSTANCE.getRoleDescriptor_ResponsibleFor(), responsibleWPDList);
				}
			}
		}
		
		refreshResponsibleForCommand.execute();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.AbstractCommand#undo()
	 */
	public void undo() {
		nestedCommandExcecutor.undoNestedCommands();
		
		// remove any object that had been added to the default configuration
		//
		if (addedObjects != null && !addedObjects.isEmpty()) {
			MethodConfiguration config = process.getDefaultContext();
			for (Iterator iter = addedObjects.iterator(); iter.hasNext();) {
				Object element = iter.next();
				if (element instanceof MethodPlugin) {
					config.getMethodPluginSelection().remove(element);
				} else if (element instanceof MethodPackage) {
					config.getMethodPackageSelection().remove(element);
				}
			}
			addedToDefaultConfig = false;
		}

		undoUpdateDescriptors();

		doUndo();
	}

	/**
	 * 
	 */
	private void undoClearDescriptors() {
		if(descriptorToOldRefreshableFeaturesMap != null) {
			for (Iterator iter = descriptorToOldRefreshableFeaturesMap.entrySet()
					.iterator(); iter.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				Descriptor desc = (Descriptor) entry.getKey();
				Map featureMap = (Map) entry.getValue();
				for (Iterator iterator = featureMap.entrySet().iterator(); iterator
				.hasNext();) {
					entry = (Map.Entry) iterator.next();
					desc
					.eSet((EStructuralFeature) entry.getKey(), entry
							.getValue());
				}
			}
		}
	}

	/**
	 * Undoes the change made by
	 * {@link #setResponsibleRoles() setResponsibleRoles() }
	 */
	private void undoSetResponsibleRole() {
//		if(wpdToOldResponsibleRoleMap != null && !wpdToOldResponsibleRoleMap.isEmpty()) {
//			for (Iterator iter = wpdToOldResponsibleRoleMap.entrySet().iterator(); iter
//			.hasNext();) {
//				Map.Entry entry = (Map.Entry) iter.next();
//				WorkProductDescriptor wpd = (WorkProductDescriptor) entry.getKey();
//				((RoleDescriptor) entry.getValue()).getResponsibleFor().remove(wpd);
//			}
//		}
		if(refreshResponsibleForCommand != null) {
			refreshResponsibleForCommand.undo();
		}
	}

	protected boolean prepare() {
		return true;
	}
	
	protected abstract void doExecute();

	protected abstract void doUndo();

	public static interface IExecutor {
		boolean preExecute();

		void doExcecute();

		void doUndo();
	}

}