//------------------------------------------------------------------------------
// 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.AbstractTreeIterator;
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.DescribableElement;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPlugin;
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();
		Collection<CustomCategory> customCategoriesToDelete = new HashSet<CustomCategory>();
		RemoveCommand cmd = null;
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof CustomCategory) {
				cmd = getRemoveCommand(element);
				if (cmd.getFeature() instanceof EReference
						&& ((EReference) cmd.getFeature()).isContainment()
						&& cmd.getOwnerList().contains(element)) {
					customCategoriesToDelete.add((CustomCategory) element);
				}
			}
		}
		
		if (!customCategoriesToDelete.isEmpty()) {
			ArrayList<CustomCategory> topCustomCategoriesToDelete = new ArrayList<CustomCategory>(
					customCategoriesToDelete);
			// find all subcategories in the same plug-in that are not
			// referenced by
			// any other custom category to delete them as well
			//
			Iterator<CustomCategory> iter = new AbstractTreeIterator<CustomCategory>(
					new ArrayList<CustomCategory>(
							topCustomCategoriesToDelete), false) {

				private static final long serialVersionUID = 1L;

				@Override
				protected Iterator<? extends CustomCategory> getChildren(
						Object object) {
					if (object instanceof Collection) {
						return ((Collection) object).iterator();
					}
					ArrayList<CustomCategory> children = new ArrayList<CustomCategory>();
					CustomCategory cc = ((CustomCategory) object);
					MethodPlugin plugin = UmaUtil.getMethodPlugin(cc);
					for (DescribableElement element : cc
							.getCategorizedElements()) {
						if (element instanceof CustomCategory
								&& UmaUtil.getMethodPlugin(element) == plugin) {
							children.add((CustomCategory) element);
						}
					}
					return children.iterator();
				}

			};
			HashSet<CustomCategory> allCustomCategories = new HashSet<CustomCategory>();
			while(iter.hasNext()) {
				allCustomCategories.add(iter.next());
			}
			int size;
			do {
				size = customCategoriesToDelete.size();
				check_cc:
				for (CustomCategory cc : allCustomCategories) {
					if (!customCategoriesToDelete.contains(cc)) {
						List parents = AssociationHelper
								.getCustomCategories(cc);
						for (Object parent : parents) {
							if (!customCategoriesToDelete.contains(parent)) {
								// parent is not in the collection of custom
								// categories to be deleted
								// cannot delete the sub custom category for now
								//
								continue check_cc;
							}
						}
						customCategoriesToDelete.add(cc);
					}
				}
			} while (size != customCategoriesToDelete.size());
			customCategoriesToDelete.removeAll(topCustomCategoriesToDelete);
			elements.addAll(customCategoriesToDelete);
			Collection collection = cmd.getCollection();
			collection.addAll(customCategoriesToDelete);
		}
	}

	/**
	 * 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()) {
			descriptors.clear();
			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));
								removeReferenceFollowUp(referencer, referenced, feature);
							} 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;
	}
	
	protected void removeReferenceFollowUp(EObject referencer,
			EObject referenced, EStructuralFeature feature) {
	}
	
}
