//------------------------------------------------------------------------------
// 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.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.IRunnableWithProgress;
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.osgi.util.NLS;

/**
 * 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];
		UserInteractionHelper.getUIHelper().runWithBusyIndicator(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,
				LibraryEditPlugin.getDefault().getContext());
		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, LibraryEditPlugin.getDefault().getContext());
				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 || vType == VariabilityType.LOCAL_CONTRIBUTION)
							&& StrUtil.isNull(act.getPresentationName())) {
						Activity base = (Activity) ref.getValue();
						batchCommand
								.addFeatureValue(
										act,
										UmaPackage.Literals.METHOD_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;
	}
	
	
}
