//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import 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.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
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.util.AbstractTreeIterator;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage.Literals;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.edit.LibraryEditPlugin;
import org.eclipse.epf.library.edit.LibraryEditResources;
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.ITextReferenceReplacer;
import org.eclipse.epf.library.edit.util.Messenger;
import org.eclipse.epf.library.edit.util.Misc;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.edit.validation.AbstractStringValidator;
import org.eclipse.epf.library.edit.validation.IValidator;
import org.eclipse.epf.library.edit.validation.IValidatorFactory;
import org.eclipse.epf.library.edit.validation.NameChecker;
import org.eclipse.epf.library.edit.validation.internal.ContentElementNameValidator;
import org.eclipse.epf.library.edit.validation.internal.UniquenessValidator;
import org.eclipse.epf.library.edit.validation.internal.ValidatorFactory;
import org.eclipse.epf.services.IFileBasedLibraryPersister;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.services.Services;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.MethodUnit;
import org.eclipse.epf.uma.NamedElement;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessElement;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.edit.domain.TraceableAdapterFactoryEditingDomain;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.ContentDescriptionFactory;
import org.eclipse.epf.uma.util.MessageException;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.osgi.util.NLS;

/**
 * This command is used to add a method element to a containing method element.
 * 
 * @author Phong Nguyen Le
 * @author Shilpa Toraskar
 * @since 1.0
 */
public class MethodElementAddCommand extends CommandWrapper implements
		IResourceAwareCommand {
	public static final Map<EClass, Collection<EStructuralFeature>> typeToExcludedFeaturesFromCheck = new HashMap<EClass, Collection<EStructuralFeature>>();
	
	public static void excludeFromCheck(EClass type, EStructuralFeature feature) {
		Collection<EStructuralFeature> features = typeToExcludedFeaturesFromCheck.get(type);
		if(features == null) {
			features = new HashSet<EStructuralFeature>();
		}
		features.add(feature);
	}

	protected boolean canUndo = true;

	protected AddCommand addCommand;

	// protected Map elementToNewNameMap;
	protected Map elementToOldPluginMap;

	protected boolean removeXRefRequired;

	protected MethodPlugin ownerPlugin;

	protected ArrayList addList;

	protected MultiStatus status = new MultiStatus(LibraryEditPlugin.INSTANCE
			.getSymbolicName(), IStatus.OK, "", null); //$NON-NLS-1$

	protected boolean runWithProgress;

	protected ArrayList<EStructuralFeature> featuresToCheck;

	private ArrayList nestedCommands;

	private HashSet modifiedResources;

	public MethodElementAddCommand(Command command) {
		this(command, true);
	}

	public MethodElementAddCommand(Command command, boolean runWithProgress) {
		super(command);
		addCommand = (AddCommand) TngUtil.unwrap(command);
		setRunWithProgress(runWithProgress);
	}

	public void setRunWithProgress(boolean runWithProgress) {
		this.runWithProgress = runWithProgress;
	}

	public boolean canUndo() {
		return canUndo;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.CommandWrapper#getResult()
	 */
	public Collection getResult() {
		if (status.isOK()) {
			return super.getResult();
		}
		return Collections.EMPTY_LIST;
	}

	private void handleError(IStatus errorStatus) {
		Messenger.INSTANCE.showError(getLabel(), LibraryEditResources.createElementError_msg, errorStatus);
		status.add(errorStatus);
		status.addAll(errorStatus);
		return;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.emf.common.command.CommandWrapper#dispose()
	 */
	public void dispose() {	
		// dispose the nested commands
		if (nestedCommands != null && !nestedCommands.isEmpty()) {
			for (int i = nestedCommands.size() - 1; i > -1; i--) {
				Command cmd = (Command) nestedCommands.get(i);
				try {
					cmd.dispose();
				} catch (Exception e) {
				}
			}
		}
		super.dispose();
	}
	
	
	public void execute() {
		Object shell = LibraryEditPlugin.getDefault().getContext();
		// Check whether the owner resource can be modified.
		//
		Collection resourcesToChange = getModifiedResources();
		IStatus execStatus = UserInteractionHelper.checkModify(
				resourcesToChange, shell);
		if (!execStatus.isOK()) {
			handleError(execStatus);
			return;
		}
		execStatus = UserInteractionHelper.checkConfigurationsToUpdate(
				addCommand, shell);
		if (!execStatus.isOK()) {
			handleError(execStatus);
			return;
		}
		if (willSaveModifiedResources()
				&& !UserInteractionHelper.checkOutOfSynch(resourcesToChange)) {
			status.add(Status.CANCEL_STATUS);
			return;
		}

		// if(!checkFolder(shell)) {
		// return;
		// }

		doAdd();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.CommandWrapper#undo()
	 */
	public void undo() {
		undoNestedCommands();
		super.undo();
	}

	/**
	 * 
	 */
	private void undoNestedCommands() {
		if (nestedCommands != null && !nestedCommands.isEmpty()) {
			for (int i = nestedCommands.size() - 1; i > -1; i--) {
				Command cmd = (Command) nestedCommands.get(i);
				try {
					if (cmd.canUndo()) {
						cmd.undo();
					}
				} catch (Exception e) {
					LibraryEditPlugin.getDefault().getLogger().logError(e);
				} finally {
					try {
						cmd.dispose();
					} catch (Exception e) {
					}
				}
			}
		}
	}

	/**
	 * @return
	 */
	private boolean checkFolder(Object shell) {
		// if any of the elements to be added will be saved in its own file
		// check if the folder to save the file to can be modified
		//
		IFileBasedLibraryPersister persister = (IFileBasedLibraryPersister) Services.getLibraryPersister(Services.XMI_PERSISTENCE_TYPE);
		ArrayList foldersToCheck = new ArrayList();
		for (Iterator iter = addCommand.getCollection().iterator(); iter
				.hasNext();) {
			Object element = TngUtil.unwrap(iter.next());
			if (element instanceof MethodElement
					&& persister.hasOwnResource(element)) {
				String folder = persister.getFolderRelativePath(
								(MethodElement) element);
				MethodPlugin plugin = UmaUtil.getMethodPlugin(addCommand
						.getOwner());
				String baseFolder = null;
				if (plugin == null) {
					MethodLibrary lib = UmaUtil.getMethodLibrary(addCommand
							.getOwner());
					baseFolder = new File(lib.eResource().getURI()
							.toFileString()).getParent();
				} else {
					baseFolder = new File(plugin.eResource().getURI()
							.toFileString()).getParent();
				}
				foldersToCheck.add(baseFolder + File.separator + folder);
			}
		}
		if (!foldersToCheck.isEmpty()) {
			String[] folders = new String[foldersToCheck.size()];
			foldersToCheck.toArray(folders);
			IStatus status = Services.getFileManager()
					.checkModify(folders, shell);
			if (!status.isOK()) {
				handleError(status);
				return false;
			}
		}

		return true;
	}

	public IStatus getStatus() {
		return status;
	}

	/**
	 * @return
	 */
	private boolean isMove() {
		Command cmd = TngUtil.unwrap(command);
		if (cmd instanceof AddCommand) {
			for (Iterator iter = ((AddCommand) cmd).getCollection().iterator(); iter
					.hasNext();) {
				EObject element = (EObject) iter.next();
				if (UmaUtil.getMethodPlugin(element) == null) {
					return false;
				}
				return true;
			}
		}
		return false;
	}

	/**
	 * 
	 * @param ownerPlugin
	 * @param e
	 * @return List of Reference objects that keeps the info of illegal outgoing
	 *         references
	 * @see Reference
	 */
	public static Collection<Reference> getIllegalOutgoingReferences(
			MethodPlugin ownerPlugin, EObject e, Collection<Reference> illegalReferences) {
		if (illegalReferences == null) {
			illegalReferences = new ArrayList<Reference>();
		}
		for (EContentsEList.FeatureIterator<EObject> featureIterator = (EContentsEList.FeatureIterator<EObject>) e
				.eCrossReferences().iterator(); featureIterator.hasNext();) {
			EObject eObject = (EObject) featureIterator.next();
			EStructuralFeature feature = featureIterator.feature();
			if (!feature.isDerived()) {
				MethodPlugin plugin = UmaUtil.getMethodPlugin(eObject);
				if (plugin != null && plugin != ownerPlugin
						&& !Misc.isBaseOf(plugin, ownerPlugin)) {
					// illegal reference to be removed
					//
					illegalReferences
							.add(new Reference(e, feature, eObject, -1));
					if (feature == UmaPackage.eINSTANCE
							.getVariabilityElement_VariabilityBasedOnElement()) {
						feature = UmaPackage.eINSTANCE.getVariabilityElement_VariabilityType();
						illegalReferences
							.add(new Reference(e, feature, e.eGet(feature), -1));
					}
				}
			}
		}
		return illegalReferences;
	}

	private static void removeReferences(Collection<Reference> references) {
		for (Reference ref: references) {
			if (ref.feature.isMany()) {
				List<?> list = ((List<?>) ref.owner.eGet(ref.feature));
				list.remove(ref.value);
			} else {
				ref.owner.eSet(ref.feature, null);
			}
		}
	}

	/**
	 * @param element
	 * @return List of Reference objects
	 */
	public static Collection<Reference> removeIllegalReferences(MethodPlugin ownerPlugin,
			EObject e) {
		Collection<Reference> removeRefs = getIllegalOutgoingReferences(ownerPlugin, e,
				null);

		// remove illegal references
		//
		removeReferences(removeRefs);

		return removeRefs;
	}

	private static boolean hasNext(Iterator iter) {
		try {
			return iter.hasNext();
		} catch (RuntimeException ex) {
			throw ex;
		}
	}

	public static boolean hasIllegalReference(MethodPlugin ownerPlugin,
			EObject e, Collection moveList) {
		for (EContentsEList.FeatureIterator featureIterator = (EContentsEList.FeatureIterator) e
				.eCrossReferences().iterator(); hasNext(featureIterator);) {
			EObject eObject = (EObject) featureIterator.next();

			// check if the x-ref object is in the move list
			//
			if (!moveList.contains(eObject)) {
				MethodPlugin plugin = UmaUtil.getMethodPlugin(eObject);
				if (plugin != null && plugin != ownerPlugin
						&& !Misc.isBaseOf(plugin, ownerPlugin)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Checks if the given MethodElement is referenced illegally after the move.
	 * 
	 * @param ownerPlugin
	 * @param e
	 * @param moveList
	 * @return
	 */
	public static boolean isReferencedIllegally(MethodPlugin ownerPlugin,
			MethodElement e, Collection moveList) {
		Collection references = AssociationHelper.getReferences(e);
		for (Iterator iter = references.iterator(); iter.hasNext();) {
			MethodElement element = (MethodElement) iter.next();

			if (isExcludedFromOutgoingReferenceCheck(element)) {
				continue;
			}

			if (!moveList.contains(element)) {
				MethodPlugin plugin = UmaUtil.getMethodPlugin(element);
				if (plugin != null && plugin != ownerPlugin
						&& !Misc.isBaseOf(ownerPlugin, plugin)) {
					return true;
				}
			}
		}
		return false;
	}

	private static void checkModify(EObject element) {
		IStatus status = TngUtil.checkEdit(element, null);
		if (!status.isOK()) {
			throw new MessageException(TngUtil.getMessage(status));
		}
	}

	public static Collection removeIllegalReferencesTo(
			MethodPlugin ownerPlugin, MethodElement e, Collection moveList) {
		ArrayList affectedReferencers = new ArrayList();
		Collection references = AssociationHelper.getReferences(e);
		for (Iterator iter = references.iterator(); iter.hasNext();) {
			MethodElement element = (MethodElement) iter.next();
			if (!moveList.contains(element)) {
				MethodPlugin plugin = UmaUtil.getMethodPlugin(element);
				if (plugin != null && plugin != ownerPlugin
						&& !Misc.isBaseOf(ownerPlugin, plugin)) {
					checkModify(element);
					removeReferences(element, e);
					affectedReferencers.add(element);
				}
			}
		}
		return affectedReferencers;
	}

	/**
	 * Gets all cross references of <code>referencer</code> to
	 * <code>referenced</code>
	 * 
	 * @param referencer
	 * @param referenced
	 * @param xReferences
	 *            output collection of EStructuralFeature objects
	 * @return collection of EStructuralFeature objects
	 */
	private static Collection getXReferences(EObject referencer,
			EObject referenced, Collection xReferences) {
		if (xReferences == null) {
			xReferences = new ArrayList();
		}
		for (EContentsEList.FeatureIterator featureIterator = (EContentsEList.FeatureIterator) referencer
				.eCrossReferences().iterator(); featureIterator.hasNext();) {
			EObject eObject = (EObject) featureIterator.next();
			EStructuralFeature feature = featureIterator.feature();
			// if(feature.isMany()) {
			// if(((List)referencer.eGet(feature)).contains(referenced)) {
			// xReferences.add(feature);
			// }
			// }
			// else
			if (eObject == referenced) {
				xReferences.add(feature);
			}
		}
		return xReferences;
	}

	/**
	 * Remove all references to <code>referenced</code> from
	 * <code>referencer</code>
	 * 
	 * @param referencer
	 * @param referenced
	 * @return Collection of references to the <code>referenced</code>
	 */
	public static Collection removeReferences(EObject referencer,
			EObject referenced) {
		Collection removeRefs = getXReferences(referencer, referenced, null);

		// remove illegal references
		//
		for (Iterator iter = removeRefs.iterator(); iter.hasNext();) {
			EStructuralFeature f = (EStructuralFeature) iter.next();
			if (f.isMany()) {
				((Collection) referencer.eGet(f)).remove(referenced);
			} else {
				referencer.eSet(f, null);
			}
		}

		return removeRefs;
	}

	public static boolean hasIllegalReferenceIncludingAllChildren(
			MethodPlugin ownerPlugin, MethodElement e, Collection moveList) {
		if (ownerPlugin == UmaUtil.getMethodPlugin(e)) {
			// move within the same plugin, no further check
			//
			return false;
		}
		if (hasIllegalReference(ownerPlugin, e, moveList))
			return true;
		for (Iterator iterator = e.eAllContents(); iterator.hasNext();) {
			if (hasIllegalReference(ownerPlugin, (EObject) iterator.next(),
					moveList))
				return true;
		}
		return false;
	}

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

	protected Collection getFeaturesToCheck() {
		if (featuresToCheck == null) {
			featuresToCheck = new ArrayList<EStructuralFeature>();
			featuresToCheck.add(UmaPackage.eINSTANCE.getNamedElement_Name());
			
		}
		return featuresToCheck;
	}

	protected IValidator createValidator(EObject e, EStructuralFeature feature) {
		IValidator validator = null;

		if(addCommand.getFeature() instanceof EReference){
			validator = IValidatorFactory.INSTANCE.createValidator(addCommand.getOwner(), (EReference) addCommand.getFeature(), (EClass)null, e, feature);
		}

		return validator;
	}

	/**
	 * @param e
	 * @param objectsToCheckName
	 */
	private void getOffStringToCheckName(Object e, Collection objectsToCheckName) {
		// if(addCommand.getOwner() instanceof ContentPackage &&
		// addCommand.getFeature() ==
		// UmaPackage.eINSTANCE.getMethodPackage_ChildPackages()
		// && e instanceof ContentPackage) {
		// for (Iterator iter = ((ContentPackage)e).eAllContents();
		// iter.hasNext();) {
		// Object element = iter.next();
		// if(element instanceof ContentElement) {
		// objectsToCheckName.add(element);
		// }
		// }
		// }
		// else
		if (addCommand.getOwner() instanceof ProcessPackage
				&& addCommand.getFeature() == UmaPackage.eINSTANCE
						.getMethodPackage_ChildPackages()
				&& e instanceof ProcessPackage
				&& !(e instanceof ProcessComponent)) {
			getProcessComponents((ProcessPackage) e, objectsToCheckName);
		}
	}

	/**
	 * @param e
	 * @param objectsToCheckName
	 */
	private static void getProcessComponents(ProcessPackage pkg,
			Collection objectsToCheckName) {
		for (Iterator iter = pkg.getChildPackages().iterator(); iter.hasNext();) {
			Object childPkg = iter.next();
			if (childPkg instanceof ProcessComponent) {
				objectsToCheckName.add(childPkg);
			} else if (childPkg instanceof ProcessPackage) {
				getProcessComponents((ProcessPackage) childPkg,
						objectsToCheckName);
			}
		}
	}

	private boolean checkStringValue(NamedElement e,
			EStructuralFeature feature, Collection objectsToAdd) {
		Collection excludedFeaturesToCheck = typeToExcludedFeaturesFromCheck.get(e.eClass()); 
		if(excludedFeaturesToCheck != null && excludedFeaturesToCheck.contains(feature)) {
			return true;
		}
		
		IValidator validator = createValidator(e, feature);
		if (validator != null) {
			String newName = null;
			try {
				newName = checkStringValue(e, feature, validator, objectsToAdd);
			} catch (OperationCanceledException ex) {
				return false;
			}
			if (newName != null) {
				newName = newName.trim();
				e.eSet(feature, newName);
				featureChanged(e, feature, newName);
			}
		}
		return true;
	}

	protected boolean checkStringValue(EStructuralFeature feature) {
		ArrayList objectsToCheckName = new ArrayList();
		Collection objectsToAdd = addCommand.getCollection();

		// feature value check
		//
		for (Iterator iter = objectsToAdd.iterator(); iter.hasNext();) {
			NamedElement e = (NamedElement) iter.next();
			if (!checkStringValue(e, feature, objectsToAdd)) {
				return false;
			}

			getOffStringToCheckName(e, objectsToCheckName);
		}

		for (Iterator iter = objectsToCheckName.iterator(); iter.hasNext();) {
			NamedElement e = (NamedElement) iter.next();
			EStructuralFeature f = UmaPackage.eINSTANCE.getNamedElement_Name();
			if (!checkStringValue(e, f, objectsToCheckName)) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Subclass can override this method to deal with element change during add
	 * 
	 * @param feature
	 * @param newValue
	 */
	protected void featureChanged(EObject object, EStructuralFeature feature,
			Object newValue) {

	}

	private static Collection getElementsToCheckName(AddCommand addCommand) {
		ArrayList elements = new ArrayList(addCommand.getCollection());
		for (Iterator iter = addCommand.getCollection().iterator(); iter
				.hasNext();) {
			Object element = iter.next();
			if (element instanceof ProcessPackage) {
				// need to get all process components in this package to check
				// name
				//
				Iterator iterator = new AbstractTreeIterator(element, false) {

					/**
					 * Comment for <code>serialVersionUID</code>
					 */
					private static final long serialVersionUID = 1L;

					protected Iterator getChildren(Object object) {
						if (object instanceof ProcessComponent) {
							return Collections.EMPTY_LIST.iterator();
						} else if (object instanceof ProcessPackage) {
							return ((ProcessPackage) object).getChildPackages()
									.iterator();
						} else {
							return Collections.EMPTY_LIST.iterator();
						}
					}

				};
				while (iterator.hasNext()) {
					Object pkg = iterator.next();
					if (pkg instanceof ProcessComponent) {
						elements.add(pkg);
					}
				}
			}
		}
		return elements;
	}

	/**
	 * Checks the name of all elements to be added.
	 * 
	 * @param addCommand
	 * @return a element to new feature name map or <code>null</code> if user
	 *         canceled the operation.
	 */
	protected static Map checkName(AddCommand addCommand) {
		Collection elementsToCheck = getElementsToCheckName(addCommand);
		HashMap elementToNewNameMap = new HashMap();

		// feature value check
		//
		for (Iterator iter = elementsToCheck.iterator(); iter.hasNext();) {
			NamedElement e = (NamedElement) iter.next();
			IValidator validator;
			if (e instanceof ContentElement) {
				validator = new ContentElementNameValidator(addCommand
						.getOwner(), addCommand.getFeature(),
						(ContentElement) e, new ValidatorFactory.TypeFilter(e));
			} else {
				validator = IValidatorFactory.INSTANCE.createNameValidator(
						addCommand.getOwner(), e);
			}

			String newName = null;
			try {
				newName = checkStringValue(e, UmaPackage.eINSTANCE
						.getNamedElement_Name(), validator, elementsToCheck);
			} catch (OperationCanceledException ex) {
				return null;
			}
			if (newName != null) {
				// new name required, check if the element can be modified
				//
				IStatus status = UserInteractionHelper.checkModify(e, LibraryEditPlugin.getDefault().getContext());
				String title = LibraryEditResources.errorDialog_title; 
				String msg = MessageFormat.format(
						LibraryEditResources.errorDialog_cannotRename,
						new Object[] { TngUtil.getTypeText(e), e.getName(),
								newName });
				while (!status.isOK()) {
					IUserInteractionHandler uiHandler = ExtensionManager.getDefaultUserInteractionHandler();
					if (uiHandler != null) {
						if (uiHandler.selectOne(new int[] {
								IUserInteractionHandler.ACTION_OK,
								IUserInteractionHandler.ACTION_CANCEL }, title,
								msg, null) == IUserInteractionHandler.ACTION_CANCEL) {
							return null;
						}
					}
					else {
						// cancel the operation if there is no user interaction handler
						//
						return null;
					}
				}
				elementToNewNameMap.put(e, newName);
			}
		}

		return elementToNewNameMap;
	}

	/**
	 * Checks feature value
	 * 
	 * @param e
	 * @param feature
	 * @param validator
	 * @param objectsToAdd
	 * @return new feature value that user has choosen or <code>null</code> if
	 *         the feature value is valid
	 * @throws OperationCanceledException
	 */
	public static String checkStringValue(NamedElement e,
			EStructuralFeature feature, IValidator validator,
			Collection objectsToAdd) throws OperationCanceledException {
		// TODO: The validator is display an error message that is too long for
		// the dialog.
		// feature value check
		final StringValidator strValidator = getStringValidator();
		strValidator.setElements(objectsToAdd);
		strValidator.setFeature(feature);
		strValidator.setValidator(validator);

		String str = (String) e.eGet(feature);
		if (str != null && str.length() > 0) {
			String msg = strValidator.isValid(str);
			if (msg != null) {
				String featureTxt = TngUtil.getFeatureText(feature);
				String title = LibraryEditResources.resolveNameConflictDialog_title; 
				String dlgMsg = NLS.bind(
						LibraryEditResources.resolveNameConflictDialog_text,
						StrUtil.toLower(featureTxt), e.getName());
				String currentValue = (String) e.eGet(feature);

				IValidator inputValidator = new AbstractStringValidator() {

					public String isValid(String newText) {
						if (strValidator != null) {
							return UserInteractionHelper
									.getSimpleErrorMessage(strValidator
											.isValid(newText));
						}
						return null;
					}

				};
				IUserInteractionHandler uiHandler = ExtensionManager.getDefaultUserInteractionHandler();
				if(uiHandler != null) {
					UserInput input = new UserInput("", UserInput.TEXT, false, null, null, inputValidator, null);
					input.setInput(currentValue);
					List<UserInput> userInputs = Collections.singletonList(input);
					if(uiHandler.requestInput(title, dlgMsg, userInputs)) {
						return (String) userInputs.get(0).getInput();
					}
					else {
						throw new OperationCanceledException();
					}
				}
			}
		}

		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.CommandWrapper#getAffectedObjects()
	 */
	public Collection getAffectedObjects() {
		Collection affectedObjects = super.getAffectedObjects();
		if (affectedObjects == null) {
			EObject owner = addCommand.getOwner();
			affectedObjects = owner == null ? Collections.EMPTY_SET
					: Collections.singleton(owner);
		}
		return affectedObjects;
	}

	protected Collection getElementsToCheckForIllegalReferences() {
		return addCommand.getCollection();
	}

	private static boolean isExcludedFromOutgoingReferenceCheck(Object e) {
		// don't check on ProcessPackage, ProcessElement for illegal references
		// b/c process validation is based on configuration, not plugin
		// visibility
		//
		return e instanceof ProcessPackage || e instanceof ProcessElement;
	}

	protected String checkForIllegalReferences() {
		Collection elements = getElementsToCheckForIllegalReferences();
		addList = new ArrayList(elements);
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			EObject element = (EObject) iter.next();
			// String newName = (String) elementToNewNameMap.get(element);
			// if(newName != null) {
			// element.setName(newName);
			// }
			for (Iterator iterator = element.eAllContents(); iterator.hasNext();) {
				addList.add(iterator.next());
			}
		}

		// check if there is any illegal reference in the moved objects
		//		
		ownerPlugin = UmaUtil.getMethodPlugin(addCommand.getOwner());
		removeXRefRequired = false;
		if (ownerPlugin != null) {
			find_xPluginRef: for (Iterator iter = addCommand.getCollection()
					.iterator(); iter.hasNext();) {
				Object element = iter.next();
	
				if (isExcludedFromOutgoingReferenceCheck(element)) {
					continue find_xPluginRef;
				}
	
				if (element instanceof MethodElement) {
					if (hasIllegalReferenceIncludingAllChildren(ownerPlugin,
							(MethodElement) element, addList)) {
						removeXRefRequired = true;
						break find_xPluginRef;
					}
				}
			}
		}

		if (removeXRefRequired) {
			return LibraryEditResources.invalidReferencesError_reason; 
		}
		return null;
	}

	public Collection getModifiedResources() {
		if (modifiedResources == null) {
			modifiedResources = new HashSet();
		}
		if (addFeatureIsContainment()) {
			ILibraryPersister persister = Services.getDefaultLibraryPersister();
			boolean saveOwnerResource = false;
			for (Iterator iter = addCommand.getCollection().iterator(); iter
					.hasNext();) {
				Object e = (Object) iter.next();
				if (!persister.hasOwnResourceWithoutReferrer(e)) {
					saveOwnerResource = true;
				}
			}
			if (saveOwnerResource) {
				modifiedResources.add(addCommand.getOwner().eResource());
			}
		} else {
			modifiedResources.add(addCommand.getOwner().eResource());
		}

		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 {
					
				}
			}
		}

		return modifiedResources;
	}

	protected boolean willSaveModifiedResources() {
		return true;
	}
	
	private ILibraryPersister.FailSafeMethodLibraryPersister getPersister() {
		return Services.getDefaultLibraryPersister().getFailSafePersister();
	}

	protected void saveModifiedResources() {
		ILibraryPersister.FailSafeMethodLibraryPersister persister = getPersister();
		try {

			// save the modified resources
			//
			for (Iterator iter = getModifiedResources().iterator(); iter
					.hasNext();) {
				Resource resource = (Resource) iter.next();
				try {
					persister.save(resource);
					canUndo = false;
				} catch (Exception e) {
					LibraryEditPlugin.getDefault().getLogger().logError(e);
					String msg = NLS.bind(
							LibraryEditResources.saveFileError_reason, 
							resource.getURI().isFile() ? resource
									.getURI().toFileString() : resource.toString());
					status.add(new SaveStatus(IStatus.ERROR,
							LibraryEditPlugin.INSTANCE.getSymbolicName(),
							SaveStatus.SAVE_ERROR, msg, e));
					return;
				}
			}

			if (resMgr != null) {
				Collection elementsToCopyRefContents = new ArrayList();
				for (Iterator iter = getAffectedObjects().iterator(); iter
						.hasNext();) {
					elementsToCopyRefContents.add(TngUtil.unwrap(iter.next()));
				}

				Collection modified = resMgr.copyReferencedContents(
						elementsToCopyRefContents, elementToOldPluginMap);
				modified
						.addAll(replaceTextReferences(elementsToCopyRefContents));
				if (modified != null && !modified.isEmpty()) {
					for (Iterator iter = modified.iterator(); iter.hasNext();) {
						Resource resource = (Resource) iter.next();
						try {
							persister.save(resource);
						} catch (Exception e) {
							LibraryEditPlugin.getDefault().getLogger()
									.logError(e);
							String msg = NLS.bind(
									LibraryEditResources.saveFileError_reason,
									resource.getURI().toFileString());
							status.add(new SaveStatus(IStatus.ERROR,
									LibraryEditPlugin.INSTANCE
											.getSymbolicName(),
									SaveStatus.SAVE_ERROR, msg, e));
							return;
						}
					}
				}
			}

			persister.commit();
		} catch (RuntimeException e) {
			StringWriter msg = new StringWriter();
			e.printStackTrace(new PrintWriter(msg));
			IStatus newStatus = new SaveStatus(IStatus.ERROR,
					LibraryEditPlugin.INSTANCE.getSymbolicName(),
					SaveStatus.SAVE_ERROR, msg.toString(), e);
			status.add(newStatus);
		} finally {
			if (status.getSeverity() == IStatus.ERROR) {
				try {
					persister.rollback();
				} catch (Exception e) {
					LibraryEditPlugin.INSTANCE.log(e);
					StringWriter msg = new StringWriter();
					e.printStackTrace(new PrintWriter(msg));
					IStatus newStatus = new SaveStatus(IStatus.ERROR,
							LibraryEditPlugin.INSTANCE.getSymbolicName(),
							SaveStatus.ROLLBACK_ERROR, msg.toString(), e);
					status.add(newStatus);
				}
			}
		}
	}

	/**
	 * If textual descriptions in the copied elements contain references (URLs)
	 * to other elements within the same copied process then replace these
	 * references with references that point to the new elements in the copied
	 * structures.
	 */
	private Collection replaceTextReferences(
			Collection elementsToCopyRefContents) {
		Collection modifiedResources = new HashSet();
		ITextReferenceReplacer txtRefReplacer = ExtensionManager
				.getTextReferenceReplacer();
		if (txtRefReplacer == null)
			return modifiedResources;

		// get map
		EditingDomain ed = addCommand.getDomain();
		if (ed instanceof TraceableAdapterFactoryEditingDomain) {
			Map copyToOriginalMap = ((TraceableAdapterFactoryEditingDomain) ed)
					.getCopyToOriginalMap();
			// the TextReferenceReplacer expects a map of old-to-new. we
			// have a map of new-to-old, so convert it
			Map oldToNewObjectMap = new HashMap();
			for (Iterator iter = copyToOriginalMap.entrySet().iterator(); iter
					.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				Object key = entry.getKey();
				Object val = entry.getValue();
				if (key != null && val != null)
					oldToNewObjectMap.put(val, key);
			}
			for (Iterator iter = elementsToCopyRefContents.iterator(); iter
					.hasNext();) {
				EObject element = (EObject) iter.next();
				for (Iterator childIter = element.eAllContents(); childIter
						.hasNext();) {
					EObject child = (EObject) childIter.next();
					for (Iterator attributes = child.eClass()
							.getEAllAttributes().iterator(); attributes
							.hasNext();) {
						EAttribute attribute = (EAttribute) attributes.next();
						if (attribute.isChangeable()
								&& !attribute.isDerived()
								&& (attribute.isMany() || child
										.eIsSet(attribute))
								&& attribute.getEAttributeType()
										.getInstanceClass() == Literals.STRING
										.getInstanceClass()) {
							String text = (String) child.eGet(attribute);
							if (text != null) {
								String newtext = txtRefReplacer.replace(text,
										child, oldToNewObjectMap);
								if (!newtext.equals(text)) {
									child.eSet(attribute, newtext);
									modifiedResources.add(child.eResource());
								}
							}
						}
					}
				}
			}
		}
		return modifiedResources;
	}

	protected void doAdd() {
		try {
			// check feature values
			//
			for (Iterator iter = getFeaturesToCheck().iterator(); iter
					.hasNext();) {
				EStructuralFeature feature = (EStructuralFeature) iter.next();
				if (!checkStringValue(feature)) {
					// user canceled the operaion
					//
					return;
				}
			}

			boolean showWarning = false;
			EditingDomain ed = addCommand.getDomain();
			if (ed instanceof TraceableAdapterFactoryEditingDomain) {
				Map copyToOriginalMap = ((TraceableAdapterFactoryEditingDomain) ed)
						.getCopyToOriginalMap();

				// check first element of addCommand.getCollection()
				// if it's a key in the CopyToOriginalMap, we are pasting and
				// may need to warn the user
				// if it's not a key in the CopyToOriginalMap, then we are
				// probably adding a new element
				if (addCommand.getCollection() != null
						&& addCommand.getCollection().size() > 0
						&& copyToOriginalMap.containsKey(addCommand
								.getCollection().toArray()[0])) {
					elementToOldPluginMap = new HashMap();
					Iterator iter = copyToOriginalMap.entrySet().iterator();
					while (iter.hasNext()) {
						Map.Entry entry = (Entry) iter.next();
						if (entry.getValue() instanceof MethodElement
								&& !(entry.getValue() instanceof MethodConfiguration)) {
							MethodPlugin plugin = UmaUtil
									.getMethodPlugin((MethodElement) entry
											.getValue());
							if (plugin != null) {
								elementToOldPluginMap.put(entry.getKey(),
										plugin);
							} else {
								// plugin == null, original element was probably
								// deleted
								showWarning = true;
							}
						}
					}
				}
			}

			if (showWarning) {
					Messenger.INSTANCE
						.showWarning(
								getLabel(),
								LibraryEditResources.MethodElementAddCommand_originalNotFoundWarning_msg);
			}

			final StringBuffer msgBuff = new StringBuffer();
			IRunnableWithProgress operation = new IRunnableWithProgress() {

				public void run(IProgressMonitor monitor) {
					String msg = checkForIllegalReferences();
					if (msg != null) {
						msgBuff.append(msg);
					}
				}

			};

			IProgressMonitor defaultMonitor = null;
			if (!runWithProgress) {
				defaultMonitor = new NullProgressMonitor();
			}

			if (runWithProgress) {
				UserInteractionHelper.runWithProgress(operation,
						LibraryEditResources.checkingReferencesTask_name); 
			} else {
				try {
					operation.run(defaultMonitor);
				} catch (RuntimeException e) {
					LibraryEditPlugin.INSTANCE.log(e);
					throw e;
				} catch (Exception e) {
					LibraryEditPlugin.INSTANCE.log(e);
					throw new RuntimeException(e.toString());
				}
			}
			if (msgBuff.length() > 0) {
				IUserInteractionHandler uiHandler = ExtensionManager.getDefaultUserInteractionHandler();
				if(uiHandler  != null) {
					int ret = uiHandler.selectOne(new int[] {IUserInteractionHandler.ACTION_YES, IUserInteractionHandler.ACTION_NO }, 
							getLabel(), msgBuff.toString(), null);
					if(ret == IUserInteractionHandler.ACTION_NO) {
						return;
					}
				}
			}

			status = new MultiStatus(
					LibraryEditPlugin.INSTANCE.getSymbolicName(),
					IStatus.OK,
					LibraryEditResources.MethodElementAddCommand_errorSavingFiles,
					null); 
			operation = new IRunnableWithProgress() {

				public void run(IProgressMonitor monitor) {
					if (removeXRefRequired) {
						monitor.subTask(""); //$NON-NLS-1$

						for (Iterator iter = addList.iterator(); iter.hasNext();) {
							EObject element = (EObject) iter.next();
							if (element instanceof MethodElement) {
								removeIllegalReferences(ownerPlugin, element);
							}
						}
					}

					// add the elements
					//
					superExecute();

					executeNestedCommands();

					if (willSaveModifiedResources()) {
						IStatus result = saveNewElementsWithOwnResource();
						if (result.isOK()) {
							monitor
									.subTask(LibraryEditResources.savingModifiedFilesTask_name); 
							saveModifiedResources();
						} else {
							status.add(result);
						}
					}

					if (!status.isOK()) {
						// FIXME: this causes dead-lock at
						// LibraryProcessor.notifyListeners(). The method
						// is synchronized, this might be the cause of the
						// dead-lock
						//
						undo();
						
						if(CommandStatusChecker.hasRollbackError(status)) {
							Collection<?> createdElements = command.getResult();
							ILibraryPersister persister = Services.getDefaultLibraryPersister();
							for (Object object : createdElements) {
								if(object instanceof MethodElement) {
									try {
										persister.delete((MethodElement) object);
									}
									catch(Exception e) {
										LibraryEditPlugin.getDefault().getLogger().logError(e);
									}
								}
							}								
						}						
					}
				}

			};
			if (runWithProgress) {
				UserInteractionHelper.runWithProgress(operation, ""); //$NON-NLS-1$
			} else {
				try {
					operation.run(defaultMonitor);
				} catch (RuntimeException e) {
					LibraryEditPlugin.INSTANCE.log(e);
					throw e;
				} catch (Exception e) {
					LibraryEditPlugin.INSTANCE.log(e);
					throw new RuntimeException(e.toString());
				}
			}

			if (!status.isOK()) {
				Messenger.INSTANCE.showError(getLabel(), LibraryEditResources.error_msgWithDetails, status);
				return;
			}
		} catch (RuntimeException e) {
			Messenger.INSTANCE.showError(getLabel(), LibraryEditResources.error_msg, null, e);
		}
	}

	private boolean addFeatureIsContainment() {
		return addCommand.getFeature() instanceof EReference
				&& ((EReference) addCommand.getFeature()).isContainment();
	}

	/**
	 * Saves added elements that are new to the library and can have own
	 * resource that no other resource refers to (like MethodConfiguration)
	 * 
	 * @throws Exception
	 */
	protected IStatus saveNewElementsWithOwnResource() {
		if (addFeatureIsContainment()) {
			ILibraryPersister persister = Services.getDefaultLibraryPersister();
			for (Iterator iter = addList.iterator(); iter.hasNext();) {
				Object element = iter.next();
				if (element instanceof MethodElement) {
					MethodElement me = (MethodElement) element;

					if (me instanceof ContentElement ||
						me instanceof MethodPlugin || 
						me instanceof MethodConfiguration) {						
						IStatus is = checkFilePathLengthBeforeSave(me);
						if (is != null) {
							return is;
						}
					}

					if (persister.hasOwnResourceWithoutReferrer(me)) {
						try {
							persister.save(me);
						} catch (Exception e) {
							LibraryEditPlugin.getDefault().getLogger()
									.logError(e);
							String msg = e.getMessage();
							if (StrUtil.isBlank(msg)) {
								msg = e.toString();
							}
							return new SaveStatus(IStatus.ERROR,
									LibraryEditPlugin.INSTANCE
											.getSymbolicName(),
									SaveStatus.SAVE_ERROR, msg, e);
						}
					}
				}
			}
		}

		return Status.OK_STATUS;
	}

	private IStatus checkFilePathLengthBeforeSave(MethodElement element) {
		MethodElement parentElementWithResource = null;
		if (element instanceof MethodPlugin || element instanceof MethodConfiguration) {
			parentElementWithResource = UmaUtil.getMethodLibrary(element);
		} else {
			parentElementWithResource = UmaUtil.getMethodPlugin(element);
		}
		if (! NameChecker.checkFilePathLength(parentElementWithResource, element, element.getName(), 
				IValidator.MaxFilePathNameLength, null)) {
			String msg = NLS.bind(LibraryEditResources.filePathNameTooLong_msg, 
					new Object[] { new Integer(IValidator.MaxFilePathNameLength) } );
			return new SaveStatus(IStatus.ERROR,
					LibraryEditPlugin.INSTANCE
							.getSymbolicName(),
					SaveStatus.SAVE_ERROR, msg, null);
		}
		return null;
	}

	/**
	 * 
	 */
	protected void executeNestedCommands() {
		List nestedCommandProviders = ExtensionManager
				.getNestedCommandProviders();
		if (!nestedCommandProviders.isEmpty()) {
			if (!addList.isEmpty()) {
				nestedCommands = new ArrayList();
				for (Iterator iter = nestedCommandProviders.iterator(); iter
						.hasNext();) {
					INestedCommandProvider cmdProvider = (INestedCommandProvider) iter
							.next();
					try {
						Command cmd = cmdProvider.createRelatedObjects(addList,
								this);
						if (cmd != null && cmd.canExecute()) {
							cmd.execute();
							nestedCommands.add(cmd);
						}
					} catch (Exception e) {
						LibraryEditPlugin.getDefault().getLogger().logError(e);
					}
				}
			}
		}

	}

	private static class ContainmentInfo {
		EObject container;

		int index;

		ContainmentInfo(EObject container, int index) {
			this.container = container;
			this.index = index;
		}
	}

	private static class IllegalReferenceRemover {
		private MethodPlugin targetPlugin;

		private Collection elementsToMove;

		/**
		 * list of Reference objects
		 * 
		 * @see Reference
		 */
		private List illegalReferences;

		private Set affectedResources;

		private ArrayList removedReferences;

		private boolean searchOutgoingRefs;

		private boolean searchIncomingRefs;

		public IllegalReferenceRemover(MethodPlugin targetPlugin,
				Collection elementsToMove, boolean searchOutgoingRefs,
				boolean searchIncomingRefs) {
			this.targetPlugin = targetPlugin;
			this.elementsToMove = elementsToMove;
			this.searchOutgoingRefs = searchOutgoingRefs;
			this.searchIncomingRefs = searchIncomingRefs;
		}

		public Set getAffectedResources() {
			if (affectedResources == null) {
				illegalReferences = new ArrayList();
				for (Iterator iterator = elementsToMove.iterator(); iterator
						.hasNext();) {
					Object obj = iterator.next();

					if (obj instanceof MethodElement) {
						MethodElement e = (MethodElement) obj;

						// get outgoing references
						//
						if (searchOutgoingRefs
								&& !isExcludedFromOutgoingReferenceCheck(obj)) {
							getIllegalOutgoingReferences(targetPlugin, e,
									illegalReferences);
						}

						// get incoming references
						//
						if (searchIncomingRefs) {
							Collection references = AssociationHelper
									.getReferences(e);
							for (Iterator iter = references.iterator(); iter
									.hasNext();) {
								MethodElement element = (MethodElement) iter
										.next();
								if (!elementsToMove.contains(element)) {
									MethodPlugin plugin = UmaUtil
											.getMethodPlugin(element);
									if (plugin != null
											&& plugin != targetPlugin
											&& !Misc.isBaseOf(targetPlugin,
													plugin)) {
										Collection xRefs = getXReferences(
												element, e, null);
										for (Iterator iter1 = xRefs.iterator(); iter1
												.hasNext();) {
											EStructuralFeature f = (EStructuralFeature) iter1
													.next();
											illegalReferences
													.add(new Reference(element,
															f, e));
										}

									}
								}
							}
						}
					}
				}

				affectedResources = new HashSet();
				for (Iterator iter = illegalReferences.iterator(); iter
						.hasNext();) {
					Reference ref = (Reference) iter.next();
					if (ref.owner.eResource() != null) {
						affectedResources.add(ref.owner.eResource());
					}
				}
			}
			return affectedResources;
		}

		public void removeIllegalReferences() {
			removedReferences = new ArrayList();
			for (Iterator iter = illegalReferences.iterator(); iter.hasNext();) {
				Reference ref = (Reference) iter.next();
				if (ref.feature.isMany()) {
					List list = ((List) ref.owner.eGet(ref.feature));
					// TODO: needs revisit
					// This code throws
					// org.eclipse.emf.common.util.BasicEList$BasicIndexOutOfBoundsException
					// sometimes
					//
					// if(ref.index != -1) {
					// list.remove(ref.index);
					// }
					// else {
					// list.remove(ref.value);
					// }

					list.remove(ref.value);
				} else {
					if (ref.feature == UmaPackage.eINSTANCE
							.getVariabilityElement_VariabilityType()) {
						//Should query the default value if extended for any attribute feature
						ref.owner.eSet(ref.feature, VariabilityType.NA);
					} else {
						ref.owner.eSet(ref.feature, null);
					}
				}
				removedReferences.add(ref);
			}

		}

		public void restoreRemovedReferences() {
			if (removedReferences == null) {
				return;
			}
			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) {
						try {
							// TODO: need revisits
							//
							if (!list.contains(ref.value)) {
								if (ref.index < list.size()) {
									list.add(ref.index, ref.value);
								} else {
									list.add(ref.value);
								}
							}
						} catch (RuntimeException e) {
							throw e;
						}
					} else {
						list.add(ref.value);
					}
				} else {
					ref.owner.eSet(ref.feature, ref.value);
				}
			}
		}
	}

	public static class MoveOperation extends CommandWrapper {
		/** Constants for state of the move operation */
		private static final int STATE_START = 0;

		private static final int STATE_SAVED_FILES = 80;

		private static final int STATE_MOVED_FILES = 70;

		private static final int STATE_COPIED_RESOURCES = 90;

		private static final int STATE_END = 100;

		// private Command command;
		private AddCommand addCommand;

		private Collection moveList;

		private boolean removeXRefRequired = false;

		private boolean isRefenrecedIllegally = false;

		private MethodPlugin ownerPlugin;

		private Map elementToOldPluginMap;

		private Map elementToNewNameMap;

		private IProgressMonitor monitor;

		private Object shell;

		private HashSet movedResources;

		private MultiStatus status;

		/**
		 * Current state of the move operation, it can be one of the state
		 * constants
		 */
		private int state;

		protected Set modifiedResources;

		private IllegalReferenceRemover illegalReferenceRemover;

		private HashMap elementToOldContainerMap;

		public MoveOperation(Command command, IProgressMonitor monitor,
				Object shell) {
			super(command);
			addCommand = (AddCommand) TngUtil.unwrap(command);
			this.monitor = monitor;
			this.shell = shell;
		}
		
		public Map getElementToOldPluginMap() {
			return elementToOldPluginMap;
		}

		/**
		 * @return Returns the status.
		 */
		public IStatus getStatus() {
			return status;
		}

		/**
		 * Checks if reloading library is needed in case of move failure
		 * 
		 * @return
		 * @see #getStatus()
		 */
		public boolean reloadNeeded() {
			return status != null
					&& CommandStatusChecker.hasRollbackError(status);
		}

		public void undo() {
			// undo name change
			//
			if (elementToNewNameMap != null) {
				for (Iterator iter = elementToNewNameMap.entrySet().iterator(); iter
						.hasNext();) {
					Map.Entry entry = (Map.Entry) iter.next();
					NamedElement e = (NamedElement) entry.getKey();
					e.setName((String) entry.getValue());
				}
			}

			if (elementToOldContainerMap != null) {
				for (Iterator iter = elementToOldContainerMap.entrySet()
						.iterator(); iter.hasNext();) {
					Map.Entry entry = (Map.Entry) iter.next();
					EObject e = (EObject) entry.getKey();
					ContainmentInfo containmentInfo = (ContainmentInfo) entry
							.getValue();
					EStructuralFeature f = addCommand.getFeature();
					if (f.isMany()) {
						((List) containmentInfo.container.eGet(f)).add(
								containmentInfo.index, e);
					} else {
						containmentInfo.container.eSet(f, e);
					}
				}
			}

			if (illegalReferenceRemover != null) {
				illegalReferenceRemover.restoreRemovedReferences();
			}
		}
		
		@Override
		public void execute() {
			run();
		}
		
		public void run() {
			state = STATE_START;

			status = new MultiStatus(LibraryEditPlugin.INSTANCE
					.getSymbolicName(), IStatus.OK,
					LibraryEditResources.error_reason, null); 

			if (checkName()) {
				// check if the configurations that will be updated after this
				// command can be modified
				//
				IStatus execStatus = UserInteractionHelper
						.checkConfigurationsToUpdate(addCommand, shell);
				if (!execStatus.isOK()) {
					Messenger.INSTANCE.showError(LibraryEditResources.moveDialog_title, null, execStatus);
					return;
				}

				final StringBuffer msgBuffer = new StringBuffer();
				IRunnableWithProgress runnable = new IRunnableWithProgress() {

					public void run(IProgressMonitor monitor)
							throws InvocationTargetException,
							InterruptedException {
						monitor
								.subTask(LibraryEditResources.checkingReferencesTask_name); 
						String msg = checkForIllegalReferences();
						if (msg != null) {
							msgBuffer.append(msg);
						}
					}

				};

				IStatus stat = UserInteractionHelper.getUIHelper().runInModalContext(runnable, true, monitor, shell);
				if(!stat.isOK()) {
					status.add(stat);
					return;
				}

				if (msgBuffer.length() > 0) {
					IUserInteractionHandler uiHandler = ExtensionManager.getDefaultUserInteractionHandler();
					if(uiHandler  != null) {
						int ret = uiHandler.selectOne(new int[] {IUserInteractionHandler.ACTION_YES, IUserInteractionHandler.ACTION_NO }, 
								LibraryEditResources.moveDialog_title, msgBuffer.toString(), null);
						if(ret == IUserInteractionHandler.ACTION_NO) {
							return;
						}
					}
				}

				// save reference to old resource of all elements in the
				// moveList
				//
				final Map elementToOldResourceMap = new HashMap();
				for (Iterator iter = moveList.iterator(); iter.hasNext();) {
					EObject element = (EObject) iter.next();
					if (element instanceof MethodElement) {
						// save the reference to old resource
						//
						elementToOldResourceMap.put(element, element
								.eResource());
					}
				}

				if (removeXRefRequired || isRefenrecedIllegally) {
					// get set of resources that will be modified during this
					// move
					//
					illegalReferenceRemover = new IllegalReferenceRemover(
							ownerPlugin, moveList, removeXRefRequired,
							isRefenrecedIllegally);
					runnable = new IRunnableWithProgress() {

						public void run(IProgressMonitor monitor)
								throws InvocationTargetException,
								InterruptedException {
							monitor
									.subTask(LibraryEditResources.checkAffectedResourcesTask_name); 
							modifiedResources = illegalReferenceRemover
									.getAffectedResources();
						}

					};
					stat = UserInteractionHelper.getUIHelper().runInModalContext(runnable, true, monitor, shell);
					if(!stat.isOK()) {
						status.add(stat);
						return;
					}

					// check affected resources for unmodifiable
					execStatus = UserInteractionHelper.checkModify(
							modifiedResources, shell);
					if (!execStatus.isOK()) {
						Messenger.INSTANCE.showError(LibraryEditResources.moveDialog_title, null, execStatus);
						return;
					}

					try {
						monitor
								.subTask(LibraryEditResources.removingReferencestask_name); 
						illegalReferenceRemover.removeIllegalReferences();
					} catch (Exception e) {
						undo();
						String msg = TngUtil.toStackTraceString(e);
						status.add(new Status(IStatus.ERROR,
								LibraryEditPlugin.INSTANCE.getSymbolicName(),
								0, msg, e));
					}
				} else {
					modifiedResources = new HashSet();
					monitor.subTask(""); //$NON-NLS-1$
				}

				// set new name if there is any
				//
				for (Iterator iter = elementToNewNameMap.entrySet().iterator(); iter
						.hasNext();) {
					Map.Entry entry = (Map.Entry) iter.next();
					NamedElement element = (NamedElement) entry.getKey();
					element.setName((String) entry.getValue());
					modifiedResources.add(element.eResource());
					if (element instanceof MethodUnit) {
						movedResources.add(element.eResource());
						if (element instanceof ContentElement) {
							ContentElement e = (ContentElement) element;
							if (ContentDescriptionFactory.hasPresentation(e)) {
								movedResources.add(e.getPresentation());
							}
						}
					}
				}

				// move elements
				//
				runnable = new IRunnableWithProgress() {

					public void run(IProgressMonitor monitor)
							throws InvocationTargetException,
							InterruptedException {
						monitor
								.setTaskName(LibraryEditResources.movingTask_name); 
						doMove(monitor, elementToOldResourceMap,
								modifiedResources);
					}

				};
				stat = UserInteractionHelper.getUIHelper().runInModalContext(runnable, true, monitor, shell);
				if(!stat.isOK()) {
					undo();
					status.add(stat);
					return;
				}


				// check moved resources that are not in modifiable resources
				// for unmodifiable
				//
				List resources = new ArrayList(movedResources);
				resources.removeAll(modifiedResources);
				execStatus = UserInteractionHelper
						.checkModify(resources, shell);
				if (!execStatus.isOK()) {
					Messenger.INSTANCE.showError(LibraryEditResources.moveDialog_title, null, execStatus);

					undo();
					return;
				}

				// save resources
				//
				runnable = new IRunnableWithProgress() {

					public void run(IProgressMonitor monitor)
							throws InvocationTargetException,
							InterruptedException {
						try {
							IStatus saveStatus = save(monitor);
							if (!saveStatus.isOK()) {
								status.add(saveStatus);
							}
						} catch (RuntimeException e) {
							LibraryEditPlugin.INSTANCE.log(e);
							throw e;
						}
					}

				};
				stat = UserInteractionHelper.getUIHelper().runInModalContext(runnable, true, monitor, shell);
				if(!stat.isOK()) {
					status.add(stat);
					return;
				}

				// run nested commands
				//
				NestedCommandExcecutor nestedCommandExcecutor = new NestedCommandExcecutor(this);
				try {
					nestedCommandExcecutor.executeNestedCommands();
				}
				finally {
					nestedCommandExcecutor.dispose();
				}
			}

			state = STATE_END;
		}

		/**
		 * interacts with user
		 * 
		 * @return
		 */
		private boolean checkName() {
			elementToNewNameMap = MethodElementAddCommand.checkName(addCommand);
			return elementToNewNameMap != null;
		}

		/**
		 * Long running method
		 * 
		 * @return
		 */
		private String checkForIllegalReferences() {
			elementToOldPluginMap = new HashMap();

			moveList = new ArrayList(addCommand.getCollection());
			movedResources = new HashSet();

			for (Iterator iter = addCommand.getCollection().iterator(); iter
					.hasNext();) {
				EObject element = (EObject) iter.next();

				// // set new name if there is any
				// //
				// String newName = (String) elementToNewNameMap.get(element);
				// if(newName != null) {
				// ((NamedElement)element).setName(newName);
				// if(element instanceof MethodUnit) {
				// movedResources.add(element.eResource());
				// if(element instanceof ContentElement) {
				// ContentElement e = (ContentElement) element;
				// if(ContentDescriptionFactory.hasPresentation(e)) {
				// movedResources.add(e.getPresentation());
				// }
				// }
				// }
				// }

				if (element instanceof MethodElement) {
					elementToOldPluginMap.put(element, UmaUtil
							.getMethodPlugin(element));
				}
				for (Iterator iterator = element.eAllContents(); iterator
						.hasNext();) {
					moveList.add(iterator.next());
				}
			}

			// check if there is any illegal reference in the moved objects
			//			
			ownerPlugin = UmaUtil.getMethodPlugin(addCommand.getOwner());
			find_xPluginRef: for (Iterator iter = addCommand.getCollection()
					.iterator(); iter.hasNext();) {
				Object element = iter.next();

				if (isExcludedFromOutgoingReferenceCheck(element)) {
					continue find_xPluginRef;
				}

				if (element instanceof MethodElement) {
					if (hasIllegalReferenceIncludingAllChildren(ownerPlugin,
							(MethodElement) element, moveList)) {
						removeXRefRequired = true;
						break find_xPluginRef;
					}
				}
			}

			find_illegalReferencer: for (Iterator iter = moveList.iterator(); iter
					.hasNext();) {
				Object element = iter.next();
				if (element instanceof MethodElement) {
					if (isReferencedIllegally(ownerPlugin,
							(MethodElement) element, moveList)) {
						isRefenrecedIllegally = true;
						break find_illegalReferencer;
					}
				}
			}
			if (removeXRefRequired || isRefenrecedIllegally) {
				return LibraryEditResources.invalidReferencesError_reason; 
			}
			return null;
		}

		/**
		 * Long running method
		 * 
		 * @return
		 */
		private void doMove(IProgressMonitor monitor,
				Map elementToOldResourceMap, Set modifiedResources) {
			monitor.subTask(""); //$NON-NLS-1$

			elementToOldContainerMap = new HashMap();
			for (Iterator iter = addCommand.getCollection().iterator(); iter
					.hasNext();) {
				EObject element = (EObject) iter.next();
				if (element instanceof MethodElement) {
					EObject container = element.eContainer();
					EStructuralFeature feature = element.eContainingFeature();
					int index;
					if (feature.isMany()) {
						index = ((List) container.eGet(feature))
								.indexOf(element);
					} else {
						index = -1;
					}
					elementToOldContainerMap.put(element, new ContainmentInfo(
							container, index));
				}
			}

			// move the elements
			//
			addCommand.execute();

			// collect resources that had been modifed as result of this move
			//
			Resource newResource = addCommand.getOwner().eResource();
			modifiedResources.add(newResource);
			for (Iterator iter = addCommand.getAffectedObjects().iterator(); iter
					.hasNext();) {
				EObject element = (EObject) TngUtil.unwrap(iter.next());
				if (element instanceof MethodElement) {
					EObject oldContainer = ((ContainmentInfo) elementToOldContainerMap
							.get(element)).container;
					if (oldContainer.eResource() != newResource
							&& !oldContainer.eResource().getContents()
									.isEmpty()) {
						modifiedResources.add(oldContainer.eResource());
						Resource oldResource = (Resource) elementToOldResourceMap
								.get(element);
						if (oldContainer.eResource() != oldResource) {
							movedResources.add(oldResource);
						}
					}

					Object plugin = elementToOldPluginMap.get(element);
					if (ownerPlugin != plugin) {
						// it's a cross-plugin move, add the resources of those
						// children that have direct resource
						// to the moveResources list
						//						
						for (Iterator iterator = element.eAllContents(); iterator
								.hasNext();) {
							EObject e = (EObject) iterator.next();
							if (UmaUtil.hasDirectResource(e)) {
								movedResources.add(e.eResource());
								elementToOldPluginMap.put(e, plugin);
							}
						}

						// if(element instanceof DescribableElement &&
						// ContentDescriptionFactory.hasPresentation((DescribableElement)
						// element)) {
						// movedResources.add(((DescribableElement)element).getPresentation().eResource());
						// elementToOldPluginMap.put(((DescribableElement)element).getPresentation(),
						// plugin);
						// }
						// for (Iterator iterator = element.eAllContents();
						// iterator
						// .hasNext();) {
						// Object e = iterator.next();
						// if(e instanceof DescribableElement &&
						// ContentDescriptionFactory.hasPresentation((DescribableElement)
						// e)) {
						// movedResources.add(((DescribableElement)e).getPresentation().eResource());
						// elementToOldPluginMap.put(((DescribableElement)e).getPresentation(),
						// plugin);
						// }
						// }
					}
				}
			}
		}

		private IStatus save(IProgressMonitor monitor) {
			MultiStatus status = new MultiStatus(
					LibraryEditPlugin.INSTANCE.getSymbolicName(),
					IStatus.OK,
					LibraryEditResources.MethodElementAddCommand_errorSavingFiles,
					null); 

			monitor.subTask(LibraryEditResources.savingModifiedFilesTask_name); 
			ILibraryPersister.FailSafeMethodLibraryPersister persister = Services
					.getDefaultLibraryPersister().getFailSafePersister();
			save: do {
				try {

					if (!movedResources.isEmpty()) {
						monitor
								.subTask(LibraryEditResources.movingFilesTask_name); 

						// move the moved resources
						//
						persister.adjustLocation(movedResources);
					}
					state = STATE_MOVED_FILES;

					// save the modified resources
					//
					for (Iterator iter = modifiedResources.iterator(); iter
							.hasNext();) {
						Resource resource = (Resource) iter.next();
						try {
							// monitor.subTask(MessageFormat.format("Saving
							// ''{0}''", pathArgs));
							persister.save(resource);

						} catch (Exception e) {
							String msg = NLS.bind(
									LibraryEditResources.saveFileError_reason,
									resource.getURI().isFile() ? resource.getURI().toFileString() : resource.toString());
							status.add(new SaveStatus(IStatus.ERROR,
									LibraryEditPlugin.INSTANCE
											.getSymbolicName(),
									SaveStatus.SAVE_ERROR, msg, e));
							break save;
						}
					}
					persister.commit();
					state = STATE_SAVED_FILES;

					if (resMgr != null) {
						monitor
								.subTask(LibraryEditResources.copyingResourcesTask_name); 

						Collection elementsToCopyRefContents = new ArrayList();
						for (Iterator iter = movedResources.iterator(); iter
								.hasNext();) {
							Resource resource = (Resource) iter.next();
							elementsToCopyRefContents.addAll(resource
									.getContents());
						}

						elementsToCopyRefContents.addAll(addCommand
								.getAffectedObjects());

						Collection modified = resMgr.copyReferencedContents(
								elementsToCopyRefContents,
								elementToOldPluginMap);
						if (modified != null && !modified.isEmpty()) {
							for (Iterator iter = modified.iterator(); iter
									.hasNext();) {
								Resource resource = (Resource) iter.next();
								Object[] pathArgs = { resource.getURI().isFile() ? resource.getURI()
										.toFileString() : resource.toString()};
								try {
									monitor
											.subTask(MessageFormat
													.format(
															LibraryEditResources.savingFileTask_name,
															pathArgs)); 
									persister.save(resource);
								} catch (Exception e) {
									String msg = MessageFormat
											.format(
													LibraryEditResources.saveFileError_reason,
													pathArgs); 
									status.add(new SaveStatus(IStatus.ERROR,
											LibraryEditPlugin.INSTANCE
													.getSymbolicName(),
											SaveStatus.SAVE_ERROR, msg, e));
									break save;
								}
							}
						}
					}
					persister.commit();
					state = STATE_COPIED_RESOURCES;

				} catch (RuntimeException e) {
					StringWriter msg = new StringWriter();
					e.printStackTrace(new PrintWriter(msg));
					IStatus newStatus = new SaveStatus(IStatus.ERROR,
							LibraryEditPlugin.INSTANCE.getSymbolicName(),
							SaveStatus.SAVE_ERROR, msg.toString(), e);
					status.add(newStatus);
				} finally {
					if (status.getSeverity() == IStatus.ERROR) {
						try {
							persister.rollback();
						} catch (Exception e) {
							LibraryEditPlugin.INSTANCE.log(e);
							StringWriter msg = new StringWriter();
							e.printStackTrace(new PrintWriter(msg));
							IStatus newStatus = new SaveStatus(IStatus.ERROR,
									LibraryEditPlugin.INSTANCE
											.getSymbolicName(),
									SaveStatus.ROLLBACK_ERROR, msg.toString(),
									e);
							status.add(newStatus);
						}
					}
				}
			} while (false);

			monitor.subTask(LibraryEditResources.command_done); 
			return status;
		}
	}

	public static interface ResourceManager {

		/**
		 * Copies the content resources that are referenced by the content of
		 * the given elements that have been moved/copied to new location.
		 * 
		 * @param elements
		 *            Elements that are moved or copied.
		 * @return collection of modified resources as the result of this call.
		 */
		Collection<Resource> copyReferencedContents(Collection<MethodElement> elements,
				Map<MethodElement, MethodPlugin> elementToOldPluginMap);
	}

	public static class BasicResourceManager implements ResourceManager {

		/*
		 * (non-Javadoc)
		 * 
		 * @see com.ibm.library.edit.command.MethodElementAddCommand.ResourceManager#copyReferencedContents(java.util.Collection)
		 */
		public Collection<Resource> copyReferencedContents(Collection<MethodElement> elements,
				Map<MethodElement, MethodPlugin> elementToOldPluginMap) {
			return null;
		}

	}

	public static void setResourceManager(ResourceManager resMgr) {
		MethodElementAddCommand.resMgr = resMgr;
	}

	private static StringValidator getStringValidator() {
		if (stringValidator == null) {
			stringValidator = new StringValidator();
		}
		return stringValidator;
	}

	private static ResourceManager resMgr = null;

	private static StringValidator stringValidator = null;

	private static class StringValidator extends AbstractStringValidator {

		private Collection elements;

		private IValidator validator;

		private EStructuralFeature feature;

		/**
		 * 
		 */
		private StringValidator() {
		}

		/**
		 * @param elements
		 *            the elements to include in the check.
		 */
		public StringValidator(Collection elements, EStructuralFeature feature) {
			this.elements = elements;
			this.feature = feature;
		}

		/**
		 * Sets the elements to include in the check.
		 * 
		 * @param elements
		 *            the elements to include in the check.
		 */
		public void setElements(Collection elements) {
			this.elements = elements;
		}

		public void setFeature(EStructuralFeature feature) {
			this.feature = feature;
		}

		public void setValidator(IValidator validator) {
			this.validator = validator;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.dialogs.IInputValidator#isValid(java.lang.String)
		 */
		public String isValid(String newText) {
			if (validator instanceof UniquenessValidator) {
				EObject obj = ((UniquenessValidator) validator).getEObject();
				int classID = obj.eClass().getClassifierID();
				newText = newText.trim();
				for (Iterator iter = elements.iterator(); iter.hasNext();) {
					EObject e = (EObject) iter.next();
					String str = (String) e.eGet(feature);
					if (obj != e && classID == e.eClass().getClassifierID()
							&& newText.equalsIgnoreCase(str)) {
						// return I18nUtil.formatString(RESOURCE_BUNDLE, key,
						// data);
						return NLS
								.bind(
										LibraryEditResources.duplicateElementNameError_msg,
										newText);
					}
				}
			}
			return validator.isValid(newText);
		}

	}

}