//------------------------------------------------------------------------------
// 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.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 HashMap elementToRemovedRefsMap;

	private BatchCommand batchCommand = new BatchCommand(true);

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

	public boolean failed;

	private boolean confirmRemoveReferences;
	
	private ArrayList nestedCommands;

	/**
	 * @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 (Iterator iter = nestedCommands.iterator(); iter.hasNext();) {
					Command command = (Command) iter.next();
					command.dispose();
				}
			}
		}
		
		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);
								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();

		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); //$NON-NLS-1$

		if (!elementToRemovedRefsMap.isEmpty()) {
			// collect set of referencers
			HashSet referencers = new HashSet();
			for (Iterator iter = elementToRemovedRefsMap.values().iterator(); iter
					.hasNext();) {
				Map referencerToFeaturesMap = (Map) iter.next();
				// collect only referencer with an unidirectional or containment
				// relationship
				//
				for (Iterator iterator = referencerToFeaturesMap.entrySet()
						.iterator(); iterator.hasNext();) {
					Map.Entry entry = (Map.Entry) iterator.next();
					Collection features = (Collection) entry.getValue();
					boolean canCollect = false;
					check_ref: for (Iterator iterator1 = features.iterator(); iterator1
							.hasNext();) {
						Object f = iterator1.next();
						if (f instanceof EReference) {
							EReference ref = (EReference) f;
							if (ref.isContainment()
									|| ref.getEOpposite() == null) {
								canCollect = true;
								break check_ref;
							}
						}
					}
					if (canCollect) {
						referencers.add(entry.getKey());
					}
				}
			}

			// confirm with user before removing illegal references
			//
			if (confirmRemoveReferences) {
				MultiStatus multiStatus = new MultiStatus(
						LibraryEditPlugin.INSTANCE.getSymbolicName(), 0,
						"", null); //$NON-NLS-1$
				for (Iterator iter = referencers.iterator(); iter.hasNext();) {
					MethodElement e = (MethodElement) iter.next();
					// don't show predefined element
					//
					if (!TngUtil.isPredefined(e)) {
						String msg = NLS.bind(
								LibraryEditResources.elementType_text, e
										.eClass().getName(), 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, null) == IUserInteractionHandler.ACTION_CANCEL) {
							return;
						}
					}
				}
			}

			// check if the referencers can be changed
			//
			for (Iterator iter = referencers.iterator(); iter.hasNext();) {
				IStatus status = UserInteractionHelper.checkModify(
						(EObject) iter.next(), MsgBox.getDefaultShell());
				if (!status.isOK()) {
					Messenger.INSTANCE
							.showError(
									LibraryEditResources.deleteDialog_title,
									LibraryEditResources.deleteElementError_msg,
									status);
					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();) {
			EObject e = (EObject) iter.next();
			UmaUtil.getResources(e, deletedResources);
		}
		
		// exclude deleted resources from the set of modified resources
		//
		modifiedResources.removeAll(deletedResources);
		
		// 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);
				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("Saving resources");
					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) {
			notifyExecuted();
			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());
			}
		} else {
			if (failed) {
				notifyFailure();
			} else {
				undo();
			}
		}
	}

	/**
	 * 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 {
		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) {
					persister.delete(e);
				}
			}
		}
	}

	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();
		HashSet objectsToRemove = new HashSet();
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			MethodElement element = (MethodElement) iter.next();
			Map 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 map = (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 {
				}
			}
		}
	}
}
