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

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventObject;
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 java.util.Map.Entry;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandWrapper;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.epf.common.serviceability.MsgBox;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.edit.ICommandListener;
import org.eclipse.epf.library.edit.IReferencer;
import org.eclipse.epf.library.edit.IStatefulItemProvider;
import org.eclipse.epf.library.edit.LibraryEditPlugin;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.Providers;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.ExtensionManager;
import org.eclipse.epf.library.edit.util.Messenger;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.services.Services;
import org.eclipse.epf.services.ILibraryPersister.FailSafeMethodLibraryPersister;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;

/**
 * This command is used to delete a method element permanently. This involves
 * deleting the storage content and removing all references to this element.
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class DeleteMethodElementCommand extends CommandWrapper {

	protected Collection elements;

	private boolean refRemoved;

	public boolean executed = false;

	private Collection commandListeners;

	private FailSafeMethodLibraryPersister persister;

	protected ArrayList elementsToDeleteContent;

	protected Set<Resource> modifiedResources;

	// Map of element to Map of its referencer to features list
	//
	protected Map<EObject, Map<EObject, Collection<EStructuralFeature>>> elementToRemovedRefsMap;

	private BatchCommand batchCommand = new BatchCommand(true);

	/**
	 * List of Reference objects
	 * 
	 * @see Reference
	 */
	protected ArrayList removedReferences;

	public boolean failed;

	private boolean confirmRemoveReferences;
	
	private ArrayList<Command> nestedCommands;

	private HashSet<Descriptor> descriptors;

	/**
	 * @param command
	 * @param elements
	 *            MethodElement objects to be permanently deleted.
	 */
	public DeleteMethodElementCommand(Command command, Collection elements) {
		this(command, elements, true);
	}

	public DeleteMethodElementCommand(Command command, Collection elements,
			boolean confirmRemoveRefs) {
		super(command);
		this.elements = elements == null ? null : new ArrayList(elements);
		commandListeners = new ArrayList();
		confirmRemoveReferences = confirmRemoveRefs;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.CommandWrapper#dispose()
	 */
	public void dispose() {
		batchCommand.dispose();
		if (commandListeners != null) {
			commandListeners.clear();
		}
		if (elements != null) {
			elements.clear();
		}
		if (elementsToDeleteContent != null) {
			elementsToDeleteContent.clear();
		}
		if (elementToRemovedRefsMap != null) {
			elementToRemovedRefsMap.clear();
		}
		if (modifiedResources != null) {
			modifiedResources.clear();
		}
		if (removedReferences != null) {
			removedReferences.clear();
		}
		// Dispose nested commands.
		if(nestedCommands != null){
			if(!nestedCommands.isEmpty()){
				for (Command command : nestedCommands) {
					command.dispose();
				}
			}
		}
		if(descriptors != null) {
			descriptors.clear();
		}
		
		super.dispose();
	}

	protected void superExecute() {
		super.execute();
	}

	private void notifyPreExecute() {
		List commandListeners = Providers
				.getCommandListeners(DeleteMethodElementCommand.class);
		if (commandListeners != null && !commandListeners.isEmpty()) {
			for (Iterator iter = commandListeners.iterator(); iter.hasNext();) {
				ICommandListener cmdListener = (ICommandListener) iter.next();
				try {
					cmdListener.preExecute(this);
				} catch (Exception e) {
					LibraryEditPlugin.getDefault().getLogger().logError(e);
				}
			}
		}
	}

	private void notifyPreUndo() {
		List commandListeners = Providers
				.getCommandListeners(DeleteMethodElementCommand.class);
		if (commandListeners != null && !commandListeners.isEmpty()) {
			for (Iterator iter = commandListeners.iterator(); iter.hasNext();) {
				ICommandListener cmdListener = (ICommandListener) iter.next();
				try {
					cmdListener.preUndo(this);
				} catch (Exception e) {
					LibraryEditPlugin.getDefault().getLogger().logError(e);
				}
			}
		}
	}

	protected void prepareElements() {
		ArrayList newElements = new ArrayList();
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof CustomCategory) {
				RemoveCommand cmd = getRemoveCommand(element);
				if (cmd.getFeature() instanceof EReference
						&& ((EReference) cmd.getFeature()).isContainment()
						&& cmd.getOwnerList().contains(element)) {
					// custom category will be deleted permanently
					// find all subcategory that are not referenced by any other
					// custom category
					// in the same plugin to delete them as well
					//
					Collection collection = TngUtil
							.getExclusiveSubCustomCategories((CustomCategory) element);
					if (!collection.isEmpty()) {
						for (Iterator iterator = collection.iterator(); iterator
								.hasNext();) {
							Object subCat = iterator.next();
							if (!elements.contains(subCat)
									&& !newElements.contains(subCat)) {
//								cmd.getCollection().add(subCat);
								Collection col = cmd.getCollection();
								col.add(subCat);								
								newElements.add(subCat);
							}
						}
					}
				}
			}
		}
		elements.addAll(newElements);
	}

	/**
	 * Gets the RemoveCommand for the given element
	 * 
	 * @param e
	 * @return
	 */
	protected RemoveCommand getRemoveCommand(Object e) {
		if (command instanceof RemoveCommand) {
			if (((RemoveCommand) command).getCollection().contains(e)) {
				return (RemoveCommand) command;
			}
		} else if (command instanceof CompoundCommand) {
			for (Iterator iter = ((CompoundCommand) command).getCommandList()
					.iterator(); iter.hasNext();) {
				Object cmd = (Object) iter.next();
				if (cmd instanceof RemoveCommand) {
					RemoveCommand removeCommand = (RemoveCommand) cmd;
					if (removeCommand.getCollection().contains(e)) {
						return removeCommand;
					}
				}
			}
		}
		return null;
	}

	public void execute() {
		prepareElements();

		notifyPreExecute();

		elementsToDeleteContent = new ArrayList();
		descriptors = new HashSet<Descriptor>();

		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object element = TngUtil.unwrap(iter.next());
			if (element instanceof MethodElement) {
				collectObjectsToDeleteContent(elementsToDeleteContent,
						(MethodElement) element);
			}
		}

		IRunnableWithProgress runnable = new IRunnableWithProgress() {

			public void run(IProgressMonitor monitor)
					throws InvocationTargetException, InterruptedException {
				prepareRemovingReferences();
			}

		};
		UserInteractionHelper.runWithProgress(runnable,
				LibraryEditResources.processingReferencesTask_name); 


		if(!confirmRemovingReferences()) {
			return;
		}
		
		modifiedResources = new HashSet<Resource>();
		Set unmodifiedResources = new HashSet();

		// get the owner resources before the elements got removed from
		// container in superExecute()
		//
		collectOwnerResources(modifiedResources, unmodifiedResources);

		superExecute();
		
		executeNestedCommands();
		
		// Collect the nested command modified resources for saving. 
		collectNestedCommandResources(modifiedResources);

		// get resources of the objects that have been affected by this command
		// until now
		//
		collectResources(modifiedResources, super.getAffectedObjects());

		modifiedResources.removeAll(unmodifiedResources);

		final Exception[] exceptions = new Exception[1];
		BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {

			public void run() {
				try {
					removeReferences();
				} catch (Exception e) {
					exceptions[0] = e;
				}
			}

		});

		if (exceptions[0] != null) {
			Messenger.INSTANCE.showError(
					LibraryEditResources.deleteDialog_title,
					LibraryEditResources.deleteElementError_msg,
					LibraryEditResources.deleteReferencesError_reason,
					exceptions[0]);
				
			undo();
			return;
		}

		modifiedResources.addAll(getReferencingResources());

		for (Iterator iter = elementsToDeleteContent.iterator(); iter.hasNext();) {
			EObject element = (EObject) iter.next();
			if (element.eContainer() != null) {
				iter.remove();
			}
		}

		elementsToDeleteContent.addAll(elements);
		
		HashSet<Resource> deletedResources = new HashSet<Resource>();
		for (Iterator iter = elementsToDeleteContent.iterator(); iter.hasNext();) {
			Object obj = iter.next();
			if (! (obj instanceof EObject)) {
				obj = TngUtil.unwrap(obj);
			}
			if (obj instanceof EObject) {
				EObject e = (EObject) obj;
				UmaUtil.getResources(e, deletedResources);
			}
		}
		
		// exclude deleted resources from the set of modified resources
		//
		modifiedResources.removeAll(deletedResources);
		
		// exclude any resource that is contained by the deleted resources
		//
		for (Iterator iter = modifiedResources.iterator(); iter.hasNext();) {
			Resource resource = (Resource) iter.next();
			for (Iterator iterator = deletedResources.iterator(); iterator
					.hasNext();) {
				Resource deletedResource = (Resource) iterator.next();
				if(getPersister().isContainedBy(resource, deletedResource)) {
					iter.remove();
				}
			}
		}		
		
		// check affected resources for unmodifiable
		//
		IStatus status = UserInteractionHelper.checkModify(modifiedResources,
				MsgBox.getDefaultShell());
		if (!status.isOK()) {
			Messenger.INSTANCE.showError(
					LibraryEditResources.deleteDialog_title,
					LibraryEditResources.deleteElementError_msg, status);

			undo();
			return;
		}
		
		runnable = new IRunnableWithProgress() {

			public void run(IProgressMonitor monitor)
					throws InvocationTargetException, InterruptedException {
				monitor.beginTask("", 3); //$NON-NLS-1$
				getPersister();

				// save resources that had been changed after references to the
				// deleted elements
				// had been removed
				//
				try {
					monitor
							.subTask(LibraryEditResources.deletingElementsTask_name);
					monitor.worked(1);
					deleteContent();

					// save modified resources
					//
					monitor.subTask(LibraryEditResources.savingResources_msg);
					monitor.worked(1);
					for (Iterator iter = modifiedResources.iterator(); iter
							.hasNext();) {
						Resource resource = (Resource) iter.next();
						if (resource.isLoaded()) {
							persister.save(resource);
						}
					}

					persister.commit();

					executed = true;

					removeAdapters();
				} catch (Exception e) {
					LibraryEditPlugin.INSTANCE.log(e);
					try {
						persister.rollback();
					} catch (Exception ex) {
						failed = true;
					}
					if (e instanceof RuntimeException) {
						throw (RuntimeException) e;
					} else {
						throw new WrappedException(e);
					}
				}
			}

		};

		// if (!UserInteractionHelper.runWithProgress(runnable,
		// LibraryEditResources.deletingElementsTask_name)) { //$NON-NLS-1$
		// if (failed) {
		// notifyFailure();
		// } else {
		// undo();
		// }
		// return;
		// }

//		UserInteractionHelper.runInUI(runnable, (Shell) null);
		
		UserInteractionHelper.runWithProgress(runnable, LibraryEditResources.deletingElementsTask_name);

		if (executed) {
			try {
				List warnings = persister.getWarnings();
				if (!warnings.isEmpty()) {
					String title = LibraryEditResources.deleteDialog_title;
					String msg = LibraryEditResources.DeleteMethodElementCommand_warningMsg;
					StringBuffer reason = new StringBuffer();
					for (Iterator iter = warnings.iterator(); iter.hasNext();) {
						Exception e = (Exception) iter.next();
						String str = e.getMessage();
						if (!StrUtil.isBlank(str)) {
							reason.append(str).append('\n');
						}
					}

					Messenger.INSTANCE.showWarning(title, msg, reason
							.toString());
				}
			} catch (Exception e) {
				LibraryEditPlugin.getDefault().getLogger().logError(e);
			}
			
			notifyExecuted();
		} else {
			if (failed) {
				notifyFailure();
			} else {
				undo();
			}
		}
	}

	private boolean confirmRemovingReferences() {
		if (!elementToRemovedRefsMap.isEmpty()) {
			// collect set of referencers
			HashSet<EObject> referencers = new HashSet<EObject>();
			for (Map<EObject, Collection<EStructuralFeature>> referencerToFeaturesMap : elementToRemovedRefsMap.values()) {
				// collect only referencer with an unidirectional or containment
				// relationship
				//
				for (Map.Entry<EObject, Collection<EStructuralFeature>> entry : referencerToFeaturesMap.entrySet()) {
					Collection<EStructuralFeature> features = entry.getValue();
					boolean canCollect = false;
					boolean hasDescriptor = false;
					check_ref: for (EStructuralFeature f : features) {
						if (!canCollect && f instanceof EReference) {
							EReference ref = (EReference) f;
							if (ref.isContainment()
									|| ref.getEOpposite() == null) {
								canCollect = true;
							}
						}
						if(!hasDescriptor && (f == UmaPackage.eINSTANCE.getTaskDescriptor_Task()
								|| f == UmaPackage.eINSTANCE.getRoleDescriptor_Role()
								|| f == UmaPackage.eINSTANCE.getWorkProductDescriptor_WorkProduct())) {
							hasDescriptor = true;
						}
						if(canCollect && hasDescriptor) {
							break check_ref;							
						}
					}
					if (canCollect) {
						referencers.add(entry.getKey());
					}
					if(hasDescriptor && entry.getKey() instanceof Descriptor) {
						descriptors.add((Descriptor) entry.getKey());
					}
				}
			}

			// confirm with user before removing illegal references
			//
			if (confirmRemoveReferences) {				
				MultiStatus multiStatus = new MultiStatus(
						LibraryEditPlugin.INSTANCE.getSymbolicName(), 0,
						"", null); //$NON-NLS-1$
				
				if(!descriptors.isEmpty()) {
					// ask user to delete the descriptors that are associated
					// with the content element to be deleted
					//
					for (EObject e : descriptors) {
						String msg = NLS.bind(
								LibraryEditResources.elementType_text, TngUtil.getTypeText(e), TngUtil
										.getLabelWithPath(e));
						IStatus status = new Status(IStatus.INFO,
								LibraryEditPlugin.INSTANCE.getSymbolicName(),
								0, msg, null);
						multiStatus.add(status);
					}
					IUserInteractionHandler uiHandler = ExtensionManager
							.getDefaultUserInteractionHandler();
					if (uiHandler != null) {
						switch (uiHandler
								.selectOne(
										new int[] {
												IUserInteractionHandler.ACTION_YES,
												IUserInteractionHandler.ACTION_NO,
												IUserInteractionHandler.ACTION_CANCEL },
										LibraryEditResources.confirmDescriptorsDeletion_title,
										LibraryEditResources.confirmDescriptorsDeletion_msg,
										multiStatus)) {
						case IUserInteractionHandler.ACTION_CANCEL:
							return false;
						case IUserInteractionHandler.ACTION_NO:
							descriptors.clear();
						}
					}
				}
				
				if(!descriptors.isEmpty()) {
					// remove the descriptors that user wanted to delete from the referencers
					//
					referencers.removeAll(descriptors);
				}
				multiStatus = new MultiStatus(
						LibraryEditPlugin.INSTANCE.getSymbolicName(), 0,
						"", null); //$NON-NLS-1$
				for (EObject e : referencers) {
					// don't show predefined element
					//
					if (!(e instanceof MethodElement && TngUtil.isPredefined((MethodElement) e))) {
						String msg = NLS.bind(
								LibraryEditResources.elementType_text, TngUtil.getTypeText(e), TngUtil
										.getLabelWithPath(e));
						IStatus status = new Status(IStatus.INFO,
								LibraryEditPlugin.INSTANCE.getSymbolicName(),
								0, msg, null);
						multiStatus.add(status);
					}
				}
				if (multiStatus.getChildren().length > 0) {
					IUserInteractionHandler uiHandler = ExtensionManager
							.getDefaultUserInteractionHandler();
					if (uiHandler != null) {
						if (uiHandler
								.selectOne(
										new int[] {
												IUserInteractionHandler.ACTION_OK,
												IUserInteractionHandler.ACTION_CANCEL },
										LibraryEditResources.deleteReferencesDialog_title,
										LibraryEditResources.deleteReferencesDialog_text, multiStatus) == IUserInteractionHandler.ACTION_CANCEL) {
							return false;
						}
					}
				}
			}

			// check if the referencers can be changed
			//
			for (EObject e : referencers) {
				IStatus status = UserInteractionHelper.checkModify(e, MsgBox.getDefaultShell());
				if (!status.isOK()) {
					Messenger.INSTANCE
							.showError(
									LibraryEditResources.deleteDialog_title,
									LibraryEditResources.deleteElementError_msg,
									status);
					return false;
				}
			}
		}
		
		return true;
	}

	/**
	 * Disposes all stateful adapters, then removes all adapters that are
	 * attached to the given element
	 */
	private static void removeAdapters(EObject element) {
		for (Iterator iterator = new ArrayList(element.eAdapters()).iterator(); iterator
				.hasNext();) {
			Object adapter = iterator.next();
			if (adapter instanceof IStatefulItemProvider) {
				((IStatefulItemProvider) adapter).dispose();
				if (adapter instanceof ItemProviderAdapter) {
					AdapterFactory adapterFactory = ((ItemProviderAdapter) adapter)
							.getAdapterFactory();
					if (adapterFactory instanceof IReferencer) {
						((IReferencer) adapterFactory).remove(adapter);
					}
				}
			}
		}
		element.eAdapters().clear();
	}

	/**
	 * Disposes all stateful adapters, then removes all adapters that are
	 * attached to the deleted elements
	 */
	protected void removeAdapters() {
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object obj = TngUtil.unwrap(iter.next());
			if (obj instanceof EObject) {
				EObject element = (EObject) obj;
				if (element.eContainer() == null) {
					for (Iterator iterator = element.eAllContents(); iterator
							.hasNext();) {
						EObject e = (EObject) iterator.next();
						removeAdapters(e);
					}
					removeAdapters(element);
				}
			}
		}
	}

	/**
	 * 
	 */
	private void notifyFailure() {
		EventObject eventObject = new EventObject(this);

		for (Iterator iter = commandListeners.iterator(); iter.hasNext();) {
			CommandListener listener = (CommandListener) iter.next();
			listener.notifyFailure(eventObject);
		}
	}

	/**
	 * @return
	 * 
	 */
	protected FailSafeMethodLibraryPersister getPersister() {
		if (persister == null) {
			persister = Services.getDefaultLibraryPersister()
					.getFailSafePersister();
		}
		return persister;
	}

	private void notifyExecuted() {
		EventObject eventObject = new EventObject(this);

		for (Iterator iter = this.commandListeners.iterator(); iter.hasNext();) {
			CommandListener listener = (CommandListener) iter.next();
			listener.notifyExecuted(eventObject);
		}

		List commandListeners = Providers
				.getCommandListeners(DeleteMethodElementCommand.class);
		if (commandListeners != null && !commandListeners.isEmpty()) {
			for (Iterator iter = commandListeners.iterator(); iter.hasNext();) {
				ICommandListener cmdListener = (ICommandListener) iter.next();
				try {
					cmdListener.notifyExecuted(this);
				} catch (Exception e) {
					LibraryEditPlugin.getDefault().getLogger().logError(e);
				}
			}
		}
	}

	private Collection getReferencingResources() {
		HashSet referrers = new HashSet();

		// for (Iterator iter = removedReferencesMap.values().iterator();
		// iter.hasNext();) {
		// Map referrerToFeaturesMap = (Map) iter.next();
		// referrers.addAll(referrerToFeaturesMap.keySet());
		// }

		for (Iterator iter = removedReferences.iterator(); iter.hasNext();) {
			Reference ref = (Reference) iter.next();
			referrers.add(ref.owner);
		}

		HashSet resources = new HashSet();
		for (Iterator iter = referrers.iterator(); iter.hasNext();) {
			MethodElement element = (MethodElement) iter.next();
			if (element.eResource() != null) {
				resources.add(element.eResource());
			}
		}
		return resources;
	}

	/**
	 * Collects owner resources of the elements to be deleted to save later.
	 * 
	 * @param resources
	 */
	private void collectOwnerResources(Set resources, Set unmodifiedResources) {
		ILibraryPersister persister = Services.getDefaultLibraryPersister();
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object element = TngUtil.unwrap(iter.next());
			if (element instanceof MethodElement) {
				EObject container = ((MethodElement) element).eContainer();
				Resource resource = container.eResource();
				if (resource != null) {
					if (persister.hasOwnResourceWithoutReferrer(element)) {
						unmodifiedResources.add(resource);
					} else {
						resources.add(resource);
					}
				}
			}
		}
	}
	
	private static void collectResources(Set resources, Collection objects) {
		for (Iterator iter = objects.iterator(); iter.hasNext();) {
			Object element = TngUtil.unwrap(iter.next());
			if (element instanceof EObject) {
				EObject eObj = (MethodElement) element;
				if (eObj.eResource() != null) {
					resources.add(eObj.eResource());
				}
			}
		}
	}

	public void redo() {

		super.redo();
		removeReferences();

	}

	protected void deleteContent() throws Exception {
		List<MethodElement> toDeleteList = new ArrayList<MethodElement>();
		for (Iterator iter = elementsToDeleteContent.iterator(); iter.hasNext();) {
			Object element = TngUtil.unwrap(iter.next());
			if (element instanceof MethodElement) {
				MethodElement e = (MethodElement) element;
				if (e.eContainer() == null) {
					toDeleteList.add(e);
				}
			}
		}
		persister.delete(toDeleteList);
	}

	public Collection getElementsToRemoveReferences() {
		Collection list = new ArrayList();
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object element = TngUtil.unwrap(iter.next());
			if (element instanceof EObject
					&& willRemoveElementFromContainer((EObject) element)) {
				list.add(element);
			}
		}
		return list;
	}

	protected boolean canRemoveReferences(MethodElement e) {
		// if e is one of the deleted elements, make sure that it actually got
		// deleted by checking its container
		//
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object obj = TngUtil.unwrap(iter.next());
			if (e == obj) {
				return e.eContainer() == null;
			}
		}
		return true;
	}

	/**
	 * Loads all opposite features of the elements to be deleted
	 * 
	 * @return list of elements whose opposite features are loaded
	 */
	public List loadOppositeFeatures() {
		HashSet oppositeFeatures = new HashSet();
		HashSet deletedGUIDs = new HashSet();
		ArrayList elements = new ArrayList();

		for (Iterator iter = getElementsToRemoveReferences().iterator(); iter
				.hasNext();) {
			Object obj = iter.next();
			if (obj instanceof MethodElement) {
				MethodElement e = (MethodElement) obj;
				for (Iterator iterator = e.eAllContents(); iterator.hasNext();) {
					Object element = iterator.next();
					if (element instanceof MethodElement) {
						elements.add(element);
						Map oppositeFeatureMap = ((MultiResourceEObject) element)
								.getOppositeFeatureMap();
						if (oppositeFeatureMap != null
								&& !oppositeFeatureMap.isEmpty()) {
							oppositeFeatures
									.addAll(oppositeFeatureMap.keySet());
							deletedGUIDs.add(((MethodElement) element)
									.getGuid());
						}
					}
				}
				elements.add(e);
				Map oppositeFeatureMap = ((MultiResourceEObject) e)
						.getOppositeFeatureMap();
				if (oppositeFeatureMap != null && !oppositeFeatureMap.isEmpty()) {
					oppositeFeatures.addAll(oppositeFeatureMap.keySet());
					deletedGUIDs.add(((MethodElement) e).getGuid());
				}
			}
		}

		loadOppositeFeatures(new ArrayList(oppositeFeatures), deletedGUIDs);

		return elements;
	}

	private boolean isContainedByDeletedElement(EObject e) {
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object deleted = TngUtil.unwrap(iter.next());
			if (deleted instanceof EObject && UmaUtil.isContainedBy(e, deleted)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Collects objects that should be removed if <code>elementToDelete</code>
	 * will be removed from <code>references</code> of <code>referencer</code>.
	 * 
	 * @param objectsToRemove
	 *            output
	 * @param referencer
	 *            element that references to elementToDelete
	 * @param references
	 *            collection of {@link EReference} that contains elementToDelete
	 * @return true if one of the collected objects is the
	 *         <code>referencer</code> or the container of
	 *         <code>referencer</code>
	 */
	protected boolean collectObjectsToRemove(Collection objectsToRemove,
			EObject elementToDelete, EObject referencer, Collection references) {
		boolean ret = false;
		List commandListeners = Providers
				.getCommandListeners(DeleteMethodElementCommand.class);
		if (commandListeners != null && !commandListeners.isEmpty()) {
			for (Iterator iter = commandListeners.iterator(); iter.hasNext();) {
				Object cmdListener = iter.next();
				if (cmdListener instanceof IDeleteMethodElementCommandListener) {
					try {
						boolean b = ((IDeleteMethodElementCommandListener) cmdListener)
								.collectObjectsToRemove(objectsToRemove,
										elementToDelete, referencer, references);
						if (b) {
							ret = true;
						}
					} catch (Exception e) {
						LibraryEditPlugin.getDefault().getLogger().logError(e);
					}
				}
			}
		}

		return ret;
	}

	protected boolean willRemoveElementFromContainer(EObject element) {
		if (willRemoveElementFromContainer(command, element)) {
			return true;
		} else if (command instanceof CompoundCommand) {
			for (Iterator iter = ((CompoundCommand) command).getCommandList()
					.iterator(); iter.hasNext();) {
				Command cmd = (Command) iter.next();
				if (willRemoveElementFromContainer(cmd, element)) {
					return true;
				}
			}
		}
		return false;
	}

	private static boolean willRemoveElementFromContainer(Command cmd,
			EObject element) {
		if (cmd instanceof RemoveCommand) {
			RemoveCommand removeCommand = ((RemoveCommand) cmd);
			return removeCommand.getCollection().contains(element)
					&& removeCommand.getOwner() == element.eContainer();
		}
		return false;
	}

	protected void prepareRemovingReferences() {
		List elements = loadOppositeFeatures();

		elementToRemovedRefsMap = new HashMap<EObject, Map<EObject, Collection<EStructuralFeature>>>();
		HashSet objectsToRemove = new HashSet();
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			MethodElement element = (MethodElement) iter.next();
			Map<EObject, Collection<EStructuralFeature>> refMap = AssociationHelper.getReferenceMap(element);
			if (!refMap.isEmpty()) {
				for (Iterator iterator = refMap.entrySet().iterator(); iterator
						.hasNext();) {
					Map.Entry entry = (Entry) iterator.next();
					EObject referencer = (EObject) entry.getKey();
					Collection references = (Collection) entry.getValue();
					boolean b = collectObjectsToRemove(objectsToRemove,
							element, referencer, references);
					if (b || elements.contains(referencer)
							|| isContainedByDeletedElement(referencer)) {
						iterator.remove();
					}
				}
				if (!refMap.isEmpty())
					elementToRemovedRefsMap.put(element, refMap);
			}
		}

		// add entries for objectsToRemove to elementToRemovedRefsMap
		//
		for (Iterator iter = objectsToRemove.iterator(); iter.hasNext();) {
			EObject obj = (EObject) iter.next();
			Map<EObject, Collection<EStructuralFeature>> map = elementToRemovedRefsMap.get(obj);
			if (map == null) {
				map = new HashMap();
				elementToRemovedRefsMap.put(obj, map);
			}
			EObject container = obj.eContainer();
			EReference containmentFeature = obj.eContainmentFeature();
			Collection refs = (Collection) map.get(container);
			if (refs == null) {
				refs = new ArrayList();
				refs.add(containmentFeature);
				map.put(container, refs);
			} else {
				if (!refs.contains(containmentFeature)) {
					refs.add(containmentFeature);
				}
			}
		}

		// remove all bi-directional relationships
		//
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof EObject) {
				EObject eObject = (EObject) element;
				Map objToRefsMap = new HashMap();
				for (EContentsEList.FeatureIterator featureIterator = (EContentsEList.FeatureIterator) eObject
						.eCrossReferences().iterator(); featureIterator
						.hasNext();) {
					EObject eObj = (EObject) featureIterator.next();
					EReference eReference = (EReference) featureIterator
							.feature();
					if (eReference.getEOpposite() != null) {
						List refs = (List) objToRefsMap.get(eObj);
						if (refs == null) {
							refs = new ArrayList();
							objToRefsMap.put(eObj, refs);
						}
						refs.add(eReference.getEOpposite());
					}
				}
				Map map = (Map) elementToRemovedRefsMap.get(eObject);
				if (map == null) {
					elementToRemovedRefsMap.put(eObject, objToRefsMap);
				} else {
					// merge objToRefsMap to map
					//
					for (Iterator iterator = objToRefsMap.entrySet().iterator(); iterator
							.hasNext();) {
						Map.Entry entry = (Map.Entry) iterator.next();
						Object obj = entry.getKey();
						Collection refs = (Collection) entry.getValue();
						Collection existingRefs = (Collection) map.get(obj);
						if (existingRefs != null) {
							for (Iterator itor = refs.iterator(); itor
									.hasNext();) {
								Object ref = (Object) itor.next();
								if (!existingRefs.contains(ref)) {
									existingRefs.add(ref);
								}
							}
						} else {
							map.put(obj, refs);
						}
					}
				}
			}
		}

	}

	/**
	 * @param collectedObjects
	 * @param element
	 *            the element that will be deleted by this command
	 */
	protected void collectObjectsToDeleteContent(Collection collectedObjects,
			MethodElement element) {
		// this special handling is no longer needed since affected
		// subcategories are added
		// to the list of elements to be deleted
		//
		// if (element instanceof CustomCategory) {
		// // have to handle CustomCategory specially since deleting a
		// // CustomCategory might triger deleting
		// // its subcategories even the relationship between a CustomCategory
		// and
		// // its subcategories is
		// // non-containment reference
		// //
		// Iterator iter1 = new AbstractTreeIterator(element, false) {
		//
		// private static final long serialVersionUID = -6285969923138781437L;
		// protected Iterator getChildren(Object object) {
		// ArrayList children = new ArrayList();
		// Collection catElements = ((CustomCategory) object)
		// .getCategorizedElements();
		// for (Iterator iterator = catElements.iterator(); iterator
		// .hasNext();) {
		// Object e = iterator.next();
		// if (e instanceof CustomCategory) {
		// children.add(e);
		// }
		// }
		// return children.iterator();
		// }
		//
		// };
		// while (iter1.hasNext()) {
		// collectedObjects.add(iter1.next());
		// }
		// }

		List commandListeners = Providers
				.getCommandListeners(DeleteMethodElementCommand.class);
		if (commandListeners != null && !commandListeners.isEmpty()) {
			for (Iterator iter = commandListeners.iterator(); iter.hasNext();) {
				Object cmdListener = iter.next();
				if (cmdListener instanceof IDeleteMethodElementCommandListener) {
					try {
						((IDeleteMethodElementCommandListener) cmdListener)
								.collectObjectsToDeleteContent(
										collectedObjects, element);
					} catch (Exception e) {
						LibraryEditPlugin.getDefault().getLogger().logError(e);
					}
				}
			}
		}
	}

	protected void removeReferences() {
		if (refRemoved)
			return;

		if (removedReferences == null) {
			removedReferences = new ArrayList();
		} else {
			removedReferences.clear();
		}
		for (Iterator iter = elementToRemovedRefsMap.entrySet().iterator(); iter
				.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			MethodElement referenced = (MethodElement) entry.getKey();
			if (canRemoveReferences(referenced)) {
				Map removedRefMap = (Map) entry.getValue();
				for (Iterator iterator = removedRefMap.entrySet().iterator(); iterator
						.hasNext();) {
					Map.Entry ent = (Map.Entry) iterator.next();
					EObject referencer = (EObject) ent.getKey();
					Collection features = (Collection) ent.getValue();
					for (Iterator iter1 = features.iterator(); iter1.hasNext();) {
						EStructuralFeature feature = (EStructuralFeature) iter1
								.next();
						if (feature.isMany()) {
							List list = ((List) referencer.eGet(feature));

							int index = list.indexOf(referenced);
							// list.remove(index);
							if (index != -1) {
								list.remove(index);
								removedReferences.add(new Reference(referencer,
										feature, referenced, index));
							} else {
								if (TngUtil.DEBUG) {
									System.out
											.println("DeleteMethodElementCommand.removeReferences(): index=" + index + ", size=" + list.size() + ", referencer=" + referencer + ", referenced=" + referenced + ", feature=" + feature); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
								}
								// work-around: try to find the proxy and remove
								// it.
								// TODO: kind of hack, needs revisit
								//
								String guid = ((MethodElement) referenced)
										.getGuid();
								find_proxy: for (int i = 0; i < list.size(); i++) {
									InternalEObject ref = (InternalEObject) list
											.get(i);
									URI uri = ref.eProxyURI();
									if (uri != null
											&& guid.equals(uri.fragment())) {
										list.remove(i);
										removedReferences.add(new Reference(
												referencer, feature,
												referenced, i));
										break find_proxy;
									}
								}
							}
						} else {
							referencer.eSet(feature, null);
							removedReferences.add(new Reference(referencer,
									feature, referenced, -1));
						}
					}
				}
			}
		}

		if (TngUtil.DEBUG) {
			System.out
					.println("removedReferences: size=" + removedReferences.size()); //$NON-NLS-1$
		}

		batchCommand.getObjectToNewFeatureValuesMap().clear();
		for (Iterator iter = removedReferences.iterator(); iter.hasNext();) {
			Reference ref = (Reference) iter.next();
			if (ref.getFeature() == UmaPackage.Literals.VARIABILITY_ELEMENT__VARIABILITY_BASED_ON_ELEMENT) {
				batchCommand
						.addFeatureValue(
								ref.getOwner(),
								UmaPackage.Literals.VARIABILITY_ELEMENT__VARIABILITY_TYPE,
								UmaPackage.Literals.VARIABILITY_ELEMENT__VARIABILITY_TYPE
										.getDefaultValue());
				if (ref.getOwner() instanceof Activity) {
					// Fill blank presentation name of extended/locally
					// contributing activity with presentation name
					// from base activity when base is deleted
					//
					Activity act = (Activity) ref.getOwner();
					VariabilityType vType = act.getVariabilityType();
					if ((vType == VariabilityType.EXTENDS_LITERAL || vType == VariabilityType.LOCAL_CONTRIBUTION_LITERAL)
							&& StrUtil.isNull(act.getPresentationName())) {
						Activity base = (Activity) ref.getValue();
						batchCommand
								.addFeatureValue(
										act,
										UmaPackage.Literals.DESCRIBABLE_ELEMENT__PRESENTATION_NAME,
										ProcessUtil.getPresentationName(base));
					}
				}
			}
		}
		if (batchCommand.canExecute()) {
			batchCommand.execute();
		}

		refRemoved = true;
	}

	/**
	 * Subclass should override this method to resolve all target features so
	 * opposite features of the given MethodElement are fully loaded.
	 * 
	 * @param deletedGUIDs
	 * 
	 * @param e
	 */
	protected void loadOppositeFeatures(List oppositeFeatures, Set deletedGUIDs) {
		//
	}

	protected static void restoreReferences(List removedReferences) {
		for (int i = removedReferences.size() - 1; i > -1; i--) {
			Reference ref = (Reference) removedReferences.get(i);
			if (ref.feature.isMany()) {
				List list = (List) ref.owner.eGet(ref.feature);
				if (ref.index != -1) {
					// TODO: need revisits
					//
					if (!list.contains(ref.value)) {
						if (ref.index < list.size()) {
							list.add(ref.index, ref.value);
						} else {
							if (TngUtil.DEBUG) {
								System.out
										.println("DeleteMethodElementCommand.removeReferences(): index=" + ref.index + ", size=" + list.size() + ", referencer=" + ref.owner + ", referenced=" + ref.value + ", feature=" + ref.feature); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
							}
							list.add(ref.value);
						}
					} else {
						if (TngUtil.DEBUG) {
							System.out
									.println("DeleteMethodElementCommand.removeReferences(): reference already exists: referencer=" + ref.owner + ", referenced=" + ref.value + ", feature=" + ref.feature); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						}

					}
				} else {
					list.add(ref.value);
				}
			} else {
				ref.owner.eSet(ref.feature, ref.value);
			}
		}
	}

	protected void restoreReferences() {
		if (!refRemoved)
			return;

		batchCommand.undo();
		restoreReferences(removedReferences);

		refRemoved = false;
	}

	public void undo() {
		notifyPreUndo();
		try {
			super.undo();
			restoreReferences();
		} catch (Exception e) {
			LibraryEditPlugin.INSTANCE.log(e);
			notifyFailure();
		}
	}

	public Collection getAffectedObjects() {
		if (executed) {
			return super.getAffectedObjects();
		}
		return elements;
	}

	public void addCommandListener(CommandListener listener) {
		if (!commandListeners.contains(listener)) {
			commandListeners.add(listener);
		}
	}

	public void removeCommandListener(CommandListener listener) {
		commandListeners.remove(listener);
	}

	public static interface CommandListener {
		void notifyExecuted(EventObject eventObject);

		void notifyFailure(EventObject eventObject);
	}

	/**
	 * 
	 */
	protected void executeNestedCommands() {
		List nestedCommandProviders = ExtensionManager
				.getNestedCommandProviders();
		if (!nestedCommandProviders.isEmpty()) {
			if (!elements.isEmpty()) {
				nestedCommands = new ArrayList();
				for (Iterator iter = nestedCommandProviders.iterator(); iter
						.hasNext();) {
					INestedCommandProvider cmdProvider = (INestedCommandProvider) iter
							.next();
					try {
						Command cmd = cmdProvider.removeRelatedObjects(elements,
								this);
						if (cmd != null && cmd.canExecute()) {
							cmd.execute();
							nestedCommands.add(cmd);
						}
					} catch (Exception e) {
						LibraryEditPlugin.getDefault().getLogger().logError(e);
					}
				}
			}
		}
	}
	
	/**
	 * 
	 * @param modifiedResources2
	 */
	private void collectNestedCommandResources(Set<Resource> modifiedResources) {
		
		if (nestedCommands != null && !nestedCommands.isEmpty()) {
			for (int i = nestedCommands.size() - 1; i > -1; i--) {
				Command cmd = (Command) nestedCommands.get(i);
				try {
					if (cmd instanceof IResourceAwareCommand) {
						Collection resources = ((IResourceAwareCommand) cmd)
								.getModifiedResources();
						if (resources != null) {
							modifiedResources.addAll(resources);
						}
					}
				} catch (Exception e) {
					LibraryEditPlugin.getDefault().getLogger().logError(e);
				} finally {
				}
			}
		}
	}
	
	public Collection<Descriptor> getDescriptorsToDelete() {
		return descriptors;
	}
	
	public boolean isExecuted() {
		return executed;
	}
	
	
}
