//------------------------------------------------------------------------------
// 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.importing.services;

import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.epf.authoring.ui.views.LibraryView;
import org.eclipse.epf.common.ui.util.MsgDialog;
import org.eclipse.epf.export.services.DiagramHandler;
import org.eclipse.epf.importing.ImportPlugin;
import org.eclipse.epf.importing.ImportResources;
import org.eclipse.epf.library.ILibraryResourceManager;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.edit.util.MethodPluginPropUtil;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.persistence.MultiFileResourceSetImpl;
import org.eclipse.epf.persistence.MultiFileXMIHelperImpl;
import org.eclipse.epf.services.IFileBasedLibraryPersister;
import org.eclipse.epf.services.IFileManager;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.services.Services;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.DiagramElement;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodElementProperty;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.util.UmaUtil;


/**
 * Manages the importing of a library.
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public class LibraryImportManager {

	private Map<String, String> renamePluginMap = new HashMap<String, String>();
	private Map renameElementMap = new HashMap();
	private Map setElementMap = null;

	private LibraryDiffManager diffMgr;
	private ElementDiffTree rootTree;
	
	private boolean configFolderError = false;

	//protected AdapterFactoryEditingDomain editingDomain = null;

	//protected AdapterFactoryContentProvider afcp = null;

	private MethodLibrary baseLibrary = null;
	private MethodLibrary importingLibrary = null;

	// guid of replaced element id to the element in the base library
	// we need this to redirect the reference of new elements from the importing
	// libraty to the base library
	private Map replacedElementMap = new HashMap();

	// keep the new elements, we need to iterate their feature value and
	// redirect the valeu element
	// from the importing library to the base library
	private List newElements = new ArrayList();
		
	// deleted elements,
	private List deletedElements = new ArrayList();
	
	private boolean debug = ImportPlugin.getDefault().isDebugging();
	
	// list of user selected items to be imported
	List checkedList = new ArrayList();
	
	// flag to indicate the file cheout status
	IStatus fileCheckedOutStatus = null;
	
	// resource file path for new resoruces
	List newResources = new ArrayList();
	
	ResourceScanner resScanner;
	
	private DiagramHandler diagramHandler;
	
	/**
	 * Creates a new instance.
	 */
	public LibraryImportManager(LibraryDiffManager diffMgr,
			List checkedItems) {
		this.diffMgr = diffMgr;
		this.rootTree = diffMgr.getDiffTree();
		
		if ( checkedItems != null ) {
			// checkedList contains a list of ElementDiffTree objects
			// get the packages as well
			this.checkedList.addAll(checkedItems);
			for (Iterator it = checkedItems.iterator(); it.hasNext(); ) {
				ElementDiffTree diffTree = (ElementDiffTree) it.next();
				MethodElement e = diffTree.getBaseElement();
				if ( e != null ) {
					checkedList.add(e);
				}
								
				if ( e instanceof ProcessComponent ) {
					LibraryUtil.getAllChildPackages((MethodPackage)e, checkedList);
				}
				
				// also incldue the hidden root custom package if the package is the CustomCategories package
				// 150895 - Import Config: CustomCategory did not sync up by import
				if ( e instanceof MethodPackage ) {
					List children = ((MethodPackage)e).getChildPackages();
					if ( children.size() == 1 ) {
						MethodPackage pkg  = (MethodPackage)children.get(0);
						if ( TngUtil.isRootCutomCategoryPackage(pkg) ) {
							checkedList.add(pkg);
						}
					}
				}
				
				e = diffTree.getImportElement();
				if ( e != null ) {
					checkedList.add(e);
				}
				
				if ( e instanceof ProcessComponent ) {
					LibraryUtil.getAllChildPackages((MethodPackage)e, checkedList);
				}

				
				// for new item, add all the sub packages
				if ( diffTree.isNew() ) {
					if ( e instanceof MethodPlugin ) {
						checkedList.addAll(LibraryUtil.getAllPackages((MethodPlugin)e));
					} else if ( e instanceof MethodPackage ) {
						LibraryUtil.getAllChildPackages((MethodPackage)e, checkedList);
					} 
				}
			}
			
		} else {
			checkedList = null;
		}
		
		
		init();

		// Get the current library.
		baseLibrary = (MethodLibrary) this.rootTree.getBaseElement();
		importingLibrary = (MethodLibrary) this.rootTree
				.getImportElement();

		// create the resource scanner
		resScanner = new ResourceScanner(
				LibraryUtil.getLibraryRootPath(importingLibrary), 
				LibraryUtil.getLibraryRootPath(baseLibrary), renamePluginMap);
			
		diagramHandler = new DiagramHandler(
				LibraryUtil.getLibraryRootPath(importingLibrary), 
				LibraryUtil.getLibraryRootPath(baseLibrary)) {				
			//[0]: sourceFile
			//[1]: targetFile
			protected File[] getFiles(org.eclipse.epf.uma.MethodElement elem) {
				return super.getFiles(elem, false);
			}
			
		};
		
	}
		
	private void init() {
//		// Set the tree content.
//		List factories = new ArrayList();
//		factories.add(new ResourceItemProviderAdapterFactory());
//		factories.add(new UmaItemProviderAdapterFactory());
//		factories.add(new ReflectiveItemProviderAdapterFactory());
//
//		ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(
//				factories);
//		afcp = new AdapterFactoryContentProvider(adapterFactory);
//
//		BasicCommandStack commandStack = new BasicCommandStack();
//
//		// Create the editing domain with a special command stack.
//		editingDomain = new AdapterFactoryEditingDomain(adapterFactory,
//				commandStack, new HashMap());
//
	}

	private boolean isSelected(ElementDiffTree diffTree) {
		if ( checkedList == null || checkedList.contains(diffTree) ) {
			return true;
		}
		
		MethodElement e = diffTree.getBaseElement();		
		if ( e == null ) {
			e = diffTree.getImportElement();
		}
		
		return isSelected(e);
	}
	
	private boolean isSelected(MethodElement e) {
		
		if ( checkedList == null || 
				e instanceof ContentDescription || 
				e.eContainer() instanceof ContentDescription || 
				e instanceof MethodLibrary ) {
			return true;
		}
		
		if ( checkedList.size() == 0 ) {
			return false;
		}
		
		if ( e instanceof MethodConfiguration ) {
			return checkedList.contains(e);
		}
		
		MethodElement o = (MethodElement)LibraryUtil.getSelectable(e);
		if ( o == null ) {
			return false;
		} 
		
		if ( o instanceof MethodLibrary ) {
			return true;
		}
		
		return checkedList.contains(o);
	}
	
	/**
	 * Does merge from the import library into the base library.
	 */
	public void doMerge(boolean replaceExisting, IProgressMonitor monitor) throws Exception {
		configFolderError = false;
		
		if ( debug ) {
			System.out.println("Merging configuration ..."); //$NON-NLS-1$
		}
			
		// Save the library path before detaching the resource.

		if ( debug ) {
			System.out.println("loading library ..."); //$NON-NLS-1$
		}
		
		List unlockedPlugins = unlockPlugins();
		if (! unlockedPlugins.isEmpty() && (fileCheckedOutStatus != null)
				&& !fileCheckedOutStatus.isOK()) {
			// log error
			fileCheckOutError();
			return;
		}

		LibraryUtil.loadAll(baseLibrary);
		LibraryUtil.loadAll(importingLibrary);

		// Detach the new library from the current resource so it can be
		// added to a new Library Processor instance.
		LibraryUtil.detachFromResource(importingLibrary);

		// for test
		importingLibrary.setName("ImportingLib: " + importingLibrary.getName()); //$NON-NLS-1$
		
		if ( debug ) {
			System.out.println("Process configuration diff tree ..."); //$NON-NLS-1$
		}

		// before processing, save the original resources 
		// so that we can find the newly added resources
		List oldResources = new ArrayList(
				baseLibrary.eResource().getResourceSet().getResources());
		
		// Iterate each element and the necessary merges.
		processDiffTree(rootTree, replaceExisting);

		handleSetElements();
		
		if ( debug ) {
			System.out.println("perform integrity checking ..."); //$NON-NLS-1$
		}

		// perform an integrity check of the library
		// fix any danfling elements due to package/element replacement
		doIntegrityCheck();

		// now process the new resources and mark them dirst so that 
		// the data will be saved again. 
		// This step is critical since the first round only created the data structure
		// some of the cross-referenced elements might be lost on the first saving
		// for example, when create a method configuration with references to a new plugin,
		// which are not saved yet, those references will be lost.
		// 145891 - Import Configuration: default config is loss after import
		handleNewResources(oldResources);
		
		handleNameReplace(renameElementMap);
		
		diagramHandler.postRegisterElements();
		
		// get all the modified resources and resource files
		// check CM for file check-out
		if ( debug ) {
			System.out.println("check out files ..."); //$NON-NLS-1$
		}
		
		// clear resources for deleted elements
		deleteResoruces();
	
		checkModifiedFiles();
				
		if ( fileCheckedOutStatus.isOK() ) {
		 
			if ( debug ) {
				System.out.println("copying resource files ..."); //$NON-NLS-1$
			}
			resScanner.execute();
			diagramHandler.execute();

			if ( debug ) {
				System.out.println("saving library ..."); //$NON-NLS-1$
			}
			
			if (! configFolderError) {
				if (unlockedPlugins.size() > 0) {
					lockUnlockedPlugins(unlockedPlugins);
				}
				LibraryUtil.saveLibrary(baseLibrary, false, false);
			}
		} 
		else {
			fileCheckOutError();
		}	
// if ( debug ) {
// System.out.println("copying resource files ..."); //$NON-NLS-1$
// }
//
// // Copy the resource files in the current library to the new library.
// // For simplicity sake, copy all resource files if the files do not
// // exist in the target library or if the files are newer.
// String includes = "resources/**, **/resources/**"; //$NON-NLS-1$
//
// LayoutResources.copyDir(srcDir, destDir, includes, null);

		if ( debug ) {
			System.out.println("Merging configuration done..."); //$NON-NLS-1$
		}

	}
	
	private void fileCheckOutError() {
		// log error
		SafeUpdateController.syncExec(new Runnable() {
			public void run() {
				String title = ImportResources.importConfigWizard_title; 
				String msg = ImportResources.ImportConfigurationWizard_ERR_Import_configuration; 
				new MsgDialog(ImportPlugin.getDefault())
					.displayError(title, msg, fileCheckedOutStatus);
				}
		});

		if ( debug ) {
			System.out.println("Checkout files failed ..."); //$NON-NLS-1$
		}
	}
		
	private void handleNewResources(List oldResources) {
		for (Iterator it = baseLibrary.eResource().getResourceSet()
				.getResources().iterator(); it.hasNext(); ) {
			Resource res = (Resource)it.next();
			if ( !oldResources.contains(res) ) {
				logNewResource(res);
			}
		}	
	}
	
	
	/**
	 * Processes the diff tree. Only need to do the first level since the
	 * replace or add is done at the method package level.
	 */
	private void processDiffTree(ElementDiffTree diffTree,
			boolean replaceExisting) throws Exception {
		if (diffTree == null || !isSelected(diffTree) ) {
			return;
		}

		// There is a change.
		int state = diffTree.getDiffState();
		MethodElement base = diffTree.getBaseElement();
		MethodElement imp = diffTree.getImportElement();
		if (replaceExisting && (state == ElementDiffTree.DIFF_STATE_CHANGED) ) {

			if ( (base instanceof MethodConfiguration)) {
				// replace the configuration by adding the new packages into the
				// configuration
				doReplaceConfiguration((MethodConfiguration) base, (MethodConfiguration) imp);
			}
			else if ( (base instanceof MethodPlugin)) {
				// Replace the plugin with the non-package features.
				doReplacePlugin((MethodPlugin) base, (MethodPlugin) imp);
			}
			else if ( (base instanceof MethodPackage)) {
				// Replace the package.
				doReplacePackage((MethodPackage) base, (MethodPackage) imp);
			}
			else
			{
				if (debug ) {
					System.out.println("What is this: " + LibraryUtil.getTypeName(base)); //$NON-NLS-1$
				}
			}
		} else if (state == ElementDiffTree.DIFF_STATE_NEW) {
			// Add the new package from import library.
			doAdd(diffTree.getBaseParentElement(), diffTree.getImportElement()); 
		}

		// Process the children recursively if it's not a new one.
		if (state != ElementDiffTree.DIFF_STATE_NEW) {
			List children = diffTree.getChildren();
			if (children != null && children.size() > 0) {
				for (Iterator it = children.iterator(); it.hasNext();) {
					processDiffTree((ElementDiffTree) it.next(),
							replaceExisting);
				}
			}
		}
	}

	/**
	 * update the configuration by replacing the non-package features, and
	 * adding the new packages into the configuration
	 * 
	 * @param oldObj
	 *            MethodConfiguration
	 * @param newObj
	 *            MethodConfiguration
	 */
	private void doReplaceConfiguration(MethodConfiguration oldObj, MethodConfiguration newObj)
	{
		if ( isReplaced(oldObj) ) {
			return;
		}
		setReplaced(oldObj);
		
		List features = LibraryUtil.getStructuralFeatures(oldObj);
//		List properties = oldObj.getInstanceProperties();
		if (features != null) {
			for (int i = 0; i < features.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) features.get(i);
				// don't delete old feature values
				Object newValue = newObj.eGet(feature);
				setFeatureValue(oldObj, feature, newValue, false);
			}
		}
	}

// private void mergeElementList(List source, List target)
// {
// List ids = new ArrayList();
// for ( Iterator it = target.iterator(); it.hasNext(); )
// {
// MethodElement e = (MethodElement)it.next();
// ids.add(e.getGuid());
// }
//
// for ( Iterator it = source.iterator(); it.hasNext(); )
// {
// MethodElement e = (MethodElement)it.next();
// if ( !ids.contains(e.getGuid()) )
// {
// target.add(e);
// }
// }
// }

	/**
	 * replace the plugin features, but not the plugin object and it's packages
	 * 
	 * @param oldObj
	 *            MethodPlugin
	 * @param newObj
	 *            MethodPlugin
	 */
	private void doReplacePlugin(MethodPlugin oldObj, MethodPlugin newObj) {
		if ( isReplaced(oldObj) ) {
			return;
		}
		setReplaced(oldObj);
		
		List features = LibraryUtil.getStructuralFeatures(oldObj);
//		List properties = oldObj.getInstanceProperties();
		if (features != null) {
			for (int i = 0; i < features.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) features.get(i);
				if ( feature != UmaPackage.eINSTANCE.getMethodPlugin_MethodPackages() )
				{
					Object newValue = newObj.eGet(feature);
					setFeatureValue(oldObj, feature, newValue, true);
				}
				/* No, don't do this, fix the diff manager to include the root package instead
				 * 150895 - Import Config: CustomCategory did not sync up by import
				else {
					// custom categories package needs special handing
					// we need to start with the root custom category otherwise
					// all child categories will be lost
					MethodPackage oldPkg = UmaUtil.findContentPackage(oldObj, ModelStructure.DEFAULT_CUSTOM_CATEGORY_PATH);
// ContentPackage newPkg = UmaUtil.findContentPackage(newObj,
// ModelStructure.DEFAULT.DEFAULT_CUSTOM_CATEGORY_PATH);
					setReplaced(oldPkg);
					
					// find the root custom category and start from there
					CustomCategory oldCC = TngUtil.getRootCustomCategory(oldObj);
					CustomCategory newCC = TngUtil.getRootCustomCategory(newObj);
					oldPkg = (MethodPackage)oldCC.eContainer();
					setReplaced(oldPkg);
					doReplaceElement(oldCC, newCC);
				}
				*/
			}
		}

	}



	/**
	 * Replaces the atrributes and contained elements, but not the child
	 * packages
	 */
	private void doReplacePackage(MethodPackage oldObj, MethodPackage newObj) {
		if ( isReplaced(oldObj) ) {
			return;
		}
		setReplaced(oldObj);

		if ( debug ) {
			System.out.println("Replacing package " + LibraryUtil.getTypeName(oldObj)); //$NON-NLS-1$
		}
		List features = LibraryUtil.getStructuralFeatures(oldObj);
//		List properties = oldObj.getInstanceProperties();
		
		boolean isProcessPackage = oldObj instanceof ProcessPackage;
		
		if (features != null) {
			for (int i = 0; i < features.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) features.get(i);
				if ( feature == UmaPackage.eINSTANCE.getMethodPackage_ChildPackages() &&
					 !isProcessPackage)
				{					
					continue;
				}

				Object newValue = newObj.eGet(feature);
				setFeatureValue(oldObj, feature, newValue, true);
			}
		}

	}

// private MethodElement objOld = null;
// private MethodElement objNew = null;
// private void testIt() {
// if ( objOld != null ) {
// System.out.println("Old container =" + objOld.eContainer());
// System.out.println("New container =" + objNew.eContainer());
// if ( objOld.eContainer() == null ) {
// System.out.println("old is gone!");
// }
// if ( objNew.eContainer() == null ) {
// System.out.println("new is gone!");
// }
// }
// }
	
	/**
	 * replace the element by replacing the feature values, but don't replace
	 * the object if it is marked as not replaceable. recursive the feature
	 * value and replace it
	 * 
	 * @param oldObj
	 *            MethodPlugin
	 * @param newObj
	 *            MethodPlugin
	 */
	private void doReplaceElement(MethodElement oldObj, MethodElement newObj) {
		
		// check if the element is already replaced or not
		if ( isReplaced(oldObj) ) {
			return;
		}

		if ( diffMgr.selectable(oldObj) ) {
			return;
		}

		if ( !isSelected(oldObj) ) {
			return;
		}
		
		// if content description, check if it's changed or not
		if ( (oldObj instanceof ContentDescription) && (newObj instanceof ContentDescription) ) {
			if ( LibraryUtil.isIdentical((ContentDescription)oldObj, (ContentDescription)newObj) ) {
				if (debug ) {
					Resource res = oldObj.eResource();
					if ( res != null ) {
						System.out.println("Identical element not replaced: " + res.getURI().toFileString() ); //$NON-NLS-1$
					}
				}
				
				// even though the content is the same, we still need to copy the resources
				scanResources(oldObj, true);
				return;
			} 
		}
		
		// set repalced first to avoid calling into the same object recursively
		setReplaced(oldObj);
		
		if ( debug ) {
			System.out.println("Replacing element " + LibraryUtil.getTypeName(oldObj)); //$NON-NLS-1$
		}
		List features = LibraryUtil.getStructuralFeatures(oldObj);
//		List properties = oldObj.getInstanceProperties();
		if (features != null) {
			for (int i = 0; i < features.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) features.get(i);

				// package structure is handled by the diff tree
				// so we don't process the related feature
				if ( feature == UmaPackage.eINSTANCE.getMethodPlugin_MethodPackages()
						|| feature == UmaPackage.eINSTANCE.getMethodPackage_ChildPackages() 
						|| feature.isDerived() )
				{
					continue;
				}

				Object newValue = newObj.eGet(feature);
				setFeatureValue(oldObj, feature, newValue, true);
			}
		}

	}

	/**
	 * set the new value from the importing library to the old object in the
	 * base library. if the value or onle of values are not replaceable, suach
	 * as MethodLibrary, MethodPlugin, MethodPackage, etc, those values should
	 * be substitued with the one in the old library
	 * 
	 * @param element
	 * @param feature
	 * @param value
	 */
	

	static MethodElement newCont = null;
	static MethodElement newElem = null;
	private void setFeatureValue(MethodElement element, EStructuralFeature feature, Object newValue, boolean doDelete)
	{		
		if ( canIgnore(feature) ) {
			return;
		}
		
		boolean oldNotify = element.eDeliver();
		try
		{
			// turn off notifications to avoid possible deadlock or thread issue
			element.eSetDeliver(false);
			
			if ( canReset(feature) ) {
				element.eSet(feature, newValue);
			}
			else if ( feature.isMany() && newValue instanceof List)
			{
				List oldValue = (List)element.eGet(feature);
				if (feature.getName().equals("methodElementProperty")) {		//$NON-NLS-1$
					setMepFeatureValue(element, feature, oldValue, (List) newValue);
					return;
				}
				ElementListDiff diff = new ElementListDiff(oldValue, (List)newValue);
				if ( doDelete && diff.deletedItems.size() > 0 ) {
					oldValue.removeAll(diff.deletedItems);
					logRemovedElements(diff.deletedItems);
					if ( debug ) {
						System.out.println("  Deleting feature value, feature: " + feature.getName() + ",  element: "  //$NON-NLS-1$ //$NON-NLS-2$
								+ LibraryUtil.getTypeName(element) + ", values: " +  diff.deletedItems); //$NON-NLS-1$
					}
				}

				if ( diff.newItems.size() > 0 ) {					
					// save the new elements and fix the references later
					// note: the newly added feature values might not be REALLY
					// new element to the base library
					// it might be just a newly added reference, so check and
					// make sure
					// if it's old element, do replace again
					for ( Iterator itn = diff.newItems.iterator(); itn.hasNext(); ) {
						MethodElement newObj = (MethodElement)itn.next();
						
						// only process the new object if it's selected
						if ( isSelected(newObj) ) {
							MethodElement oldObj = diffMgr.getExistingElement(newObj.getGuid());
							if ( oldObj == null ) {
								oldValue.add(newObj);
								//logNewElement(newObj);
								logNewElementUnderExistingPlugin(newObj);
							} else {
								oldValue.add(oldObj);
								doReplaceElement(oldObj, newObj);
							}
						}
					}
					
					if ( debug ) {
						System.out.println("  Adding feature value, feature: " + feature.getName() + ",  element: "  //$NON-NLS-1$ //$NON-NLS-2$
								+ LibraryUtil.getTypeName(element) + ", values: " +  diff.newItems); //$NON-NLS-1$
					}
					
				}

				if ( diff.oldNewMap.size() > 0 ) {
					for ( Iterator it = diff.oldNewMap.entrySet().iterator(); it.hasNext(); ) {
						Map.Entry entry = (Map.Entry) it.next();
						MethodElement oldObj = (MethodElement)entry.getKey();
						
						// only process the new object if it's selected
						if ( !isSelected(oldObj) ) {
							continue;
						}
						
						MethodElement newObj = (MethodElement)entry.getValue();
						if ( canReset(oldObj) ) {
							if ( debug ) {
								System.out.println("  Resetting feature value, feature: " + feature.getName() + ",  element: "  //$NON-NLS-1$ //$NON-NLS-2$
										+ LibraryUtil.getTypeName(element) + ", value: " +  LibraryUtil.getTypeName(oldObj)); //$NON-NLS-1$
							}

							EcoreUtil.replace(element, feature, oldObj, newObj);
							logResetElement(newObj);
						} else {
							doReplaceElement(oldObj, newObj); 
						}
					}
				}
			}
			else if (newValue instanceof MethodElement)
			{
				// if the old and new element are the same,
				// only replace the feature value
				MethodElement o = (MethodElement)element.eGet(feature);
				MethodElement n = (MethodElement)newValue;
				
				// only process the new object if it's selected
				if ( (o == null || isSelected(o)) && isSelected(n) ) {

					if ( debug ) {
						System.out.println("  Replacinging feature value, feature: " + feature.getName() + ",  element: "  //$NON-NLS-1$ //$NON-NLS-2$
								+ LibraryUtil.getTypeName(element) + ", value: " +  LibraryUtil.getTypeName(o)); //$NON-NLS-1$
					}
	
					if ( newValue instanceof ContentDescription ) {
						// always replace content description (not reset) to
						// reserve the existing resource (xmi file)
						// since the contentDescription is unique the a method
						// element, so we don't need to compare the guid
												
						// if both object has no container, there is no such
						// description, ignore it
						if ( o.eContainer() != null || n.eContainer() != null ) {
							if ( o.eContainer() == null ) {
								element.eSet(feature, o);
							}
							doReplaceElement(o, n);						
						}
					}
					// if the element can be replaced, such as for
					// ContentDescription element
					// set the value directly
					else if ( canReset(n) ) {
						element.eSet(feature, newValue);
						//logNewElement(n);
						logNewElementUnderExistingPlugin(n);
					}
					else
					{
						if ( o != null && n != null && o.getGuid().equals(n.getGuid()) ) {
							 doReplaceElement(o, n);
						}
						else {													
							registerSetElement(element, feature, newValue);
							
							element.eSet(feature, newValue);
							//logNewElement(n);
							logNewElementUnderExistingPlugin(n);
						}
					}
				}
			}
			else if ( feature == UmaPackage.eINSTANCE.getNamedElement_Name() ) {
				// check difference name, if replace, need to rename resources if if has it's own resource
				// like content elements, plugins, configuirations, and process components					
				if (! (newValue instanceof String)) {
					throw new UnsupportedOperationException();
				}
				String oldName = (String)element.eGet(feature);
				if (!newValue.equals(oldName)) {					
					ensureUniqueNameForExistingElement(element, oldName, (String) newValue, renameElementMap);										
				}
			} else {
				element.eSet(feature, newValue);
				
				// scan and copy the resources
				scanResources(element, feature, newValue);
			}

		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		finally
		{
			element.eSetDeliver(oldNotify);
		}
	}

	private void setMepFeatureValue(MethodElement element, EStructuralFeature feature, List oldValue, List newValue) {
		int sz = newValue.size();
		if (oldValue.size() == sz) {
			if (sz == 0) {
				return;
			}
			boolean same = true;
			for (int i=0; i < sz; i++) {
				MethodElementProperty oldMep = (MethodElementProperty) oldValue.get(i);
				MethodElementProperty newMep = (MethodElementProperty) newValue.get(i);
				if (! oldMep.getName().equals(newMep.getName()) ||
					! oldMep.getValue().equals(newMep.getValue())) {
					same = false;
					break;
				}
			}
			if (same) {
				return;
			}					
		}
		oldValue.removeAll(oldValue);
		oldValue.addAll(newValue);		
	}

	private void scanResources(MethodElement element, boolean recursive) {

		if ( element == null ) {
			return;
		}
		
		List features = LibraryUtil.getStructuralFeatures(element);
//		List properties = element.getInstanceProperties();
		if (features != null) {
			for (int i = 0; i < features.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) features.get(i);
				if ( !(feature instanceof EAttribute) ) {
					continue;
				}

				Object value = element.eGet(feature);
				scanResources(element, feature, value);
			}
		}
		
		if ( !recursive ) {
			return;
		}
		
		for (Iterator it = element.eAllContents(); it.hasNext(); ) {
			EObject obj = (EObject)it.next();
			
			if (obj instanceof MethodLibrary
					|| obj instanceof MethodPlugin 
					|| obj instanceof MethodPackage 
					|| obj instanceof MethodConfiguration) {
				continue;
			}
			
			if ( obj instanceof MethodElement ) {
				scanResources((MethodElement)obj, false);
			}
		}
	}
	
	private void scanResources(MethodElement element, EStructuralFeature feature, Object newValue) {
		diagramHandler.registerElement(element);
		
		// scan the resources
		if ( feature == UmaPackage.eINSTANCE.getGuidanceDescription_Attachments() ) {
			// process the attachments
			String urls = (String)newValue;
			if ( (urls != null) && urls.length() != 0 ) {
				StringTokenizer st = new StringTokenizer(urls, "|"); // this is hardcoded somehow //$NON-NLS-1$
				while (st.hasMoreTokens() ) {
					String url = st.nextToken();
					resScanner.copyResource (element, url);
				}						
			}
		} else if ( newValue instanceof String ) {
			resScanner.scan(element, newValue.toString());
		} else if (newValue instanceof URI ) {
			MethodPlugin plugin = UmaUtil.getMethodPlugin(element);
			resScanner.copyResource ( ((URI)newValue).getPath(), plugin);
		}

	}
	
	private void doAdd(EObject owner, MethodElement newObj) throws Exception {
		if ( debug ) {
			System.out.println("Adding element " + LibraryUtil.getTypeName((MethodElement)newObj)); //$NON-NLS-1$
		}

		// the owner can only be library and package
		if (owner == null) {
			return;
		}
		
		ensureUniqueName(owner, newObj, renameElementMap);
		
		boolean error = false;
		
		if (owner instanceof MethodLibrary) {			
			// can be configuration or plugin
			if (newObj instanceof MethodPlugin) {
				MethodPlugin plugin = (MethodPlugin)newObj;
				
				MethodPluginPropUtil propUtil = MethodPluginPropUtil.getMethodPluginPropUtil();				
				if (ProcessUtil.isSynFree() && ! propUtil.isSynFree(plugin)) {
					propUtil.setSynFree(plugin, true);
				}
				
				checkModifiedFiles();				
				error = ! fileCheckedOutStatus.isOK();				
								
				// don't intitialize the storage since this will recreate the global packages
				// and such causing two set of global packages
				// 145850 - Import Configuration: CP/DPs did not shown in authering
				// ModelStorage.initialize(plugin);
				// NO, since the global packages are already created
				if (!error) {
					((MethodLibrary)owner).getMethodPlugins().add(plugin);
					try {
						MultiFileXMIHelperImpl.unmodifiedGetValue = true;
						LibraryUtil.saveLibrary((MethodLibrary)owner, false, false);
					} finally {
						MultiFileXMIHelperImpl.unmodifiedGetValue = false;
					}
				}
								
			} else if (newObj instanceof MethodConfiguration ) {
				checkModifiedFiles();				
				error = configFolderError || ! fileCheckedOutStatus.isOK();
				if (!error) {
					MethodLibrary lib = (MethodLibrary)owner;
					lib.getPredefinedConfigurations().add((MethodConfiguration)newObj);
					ILibraryPersister persister = ((MultiFileResourceSetImpl) lib.eResource().getResourceSet()).getPersister();
					if (persister instanceof IFileBasedLibraryPersister) {
						IFileBasedLibraryPersister ip = (IFileBasedLibraryPersister) persister;
						File configFolder = ip.getDefaultMethodConfigurationFolder(lib);
						if (configFolder != null) {
							ip.setDefaultMethodConfigurationFolder(lib, configFolder);
						} else {
							error = true;
							configFolderError = true;
						}
					}
					if (! error) {
						try {
							MultiFileXMIHelperImpl.unmodifiedGetValue = true;
							LibraryUtil.saveLibrary((MethodLibrary)owner, false, false);
						} finally {
							MultiFileXMIHelperImpl.unmodifiedGetValue = false;
						}
					}
				}
			} else {
				error = true;			
			}
		} else if ( (owner instanceof MethodPackage) 
				&& (owner.eContainer() != null) 
				&& (newObj instanceof MethodPackage) ) {
			((MethodPackage)owner).getChildPackages().add((MethodPackage)newObj);
		} else {
			error = true;
		}
			
		if ( error ) {
			String ownerStr = owner instanceof MethodElement ? 
					LibraryUtil.getTypeName((MethodElement)owner) : owner.toString();
					
			String msg = "can't add " + LibraryUtil.getTypeName(newObj) //$NON-NLS-1$
			+ " to " + ownerStr; //$NON-NLS-1$
			
			ImportPlugin.getDefault().getLogger().logError(msg); 
			if ( debug ) {
				System.out.println(msg);
			}
		} else {
			logNewElement(newObj);
		}
	}

	private boolean checkModifiedConfigs(MethodPlugin plugin) {
		List configList = LibraryUtil.getAssociatedConfigurations(plugin);
		List baseConfigs = baseLibrary.getPredefinedConfigurations();
		Map baseConfigMap = new HashMap();
		for (int i=0; i<baseConfigs.size(); i++) {
			MethodConfiguration config = (MethodConfiguration) baseConfigs.get(i);
			baseConfigMap.put(config.getGuid(), config);
		}
		final List modifiedFiles = new ArrayList();
		for (int i=0; i<configList.size(); i++) {
			MethodConfiguration config = (MethodConfiguration) configList.get(i);
			config = (MethodConfiguration) baseConfigMap.get(config.getGuid());
			if (config != null) {
				Resource res = config.eResource();
				if (res != null) {
					modifiedFiles.add(res.getURI().toFileString());
				}
			}
		}
		SafeUpdateController.syncExec(new Runnable() {
			public void run() {
				fileCheckedOutStatus = FileModifyChecker.checkModify(modifiedFiles);
			}
		});
		fileCheckOutError();
		
		return fileCheckedOutStatus.isOK();
	}

	private void doIntegrityCheck()
	{		
		// now the newly added elements may have feature value element that
		// still pointing to the importing library
		// we need to replace those with the one in the base library
		while (newElements.size() > 0) {
			MethodElement newObj = (MethodElement)newElements.remove(0);
			try {
				if ( newObj instanceof DiagramElement ) {
					fixDiagram((DiagramElement)newObj);
				} else {
					fixNewElementReferences(newObj);
				}
			} catch (Exception e) {
				if (debug) {
					System.out.println("Exception while fixing new element " + LibraryUtil.getTypeName(newObj)); //$NON-NLS-1$
				}
				e.printStackTrace();
			}
		}
		
		// the configurations needs to be fixed
		List configs = baseLibrary.getPredefinedConfigurations();
		for ( Iterator it = configs.iterator(); it.hasNext(); )
		{
			MethodConfiguration config = (MethodConfiguration)it.next();
			LibraryUtil.validateMethodConfiguration(null, config);
		}
	}

	private List processedNewElements = new ArrayList();
	
	
	
	/**
	 * iterate all features, if the feature value references an element which is
	 * an old element, replace it with the old element. if the element is new,
	 * iterate it's containment elements
	 * 
	 * @param newObj
	 */
	private void fixNewElementReferences(MethodElement newObj) {
		if ( processedNewElements.contains(newObj) ) {
			return;
		}
		
		processedNewElements.add(newObj);
		
		if ( debug ) {
			System.out.println("Fixing element " + LibraryUtil.getTypeName(newObj)); //$NON-NLS-1$
		}
		
		List features = LibraryUtil.getStructuralFeatures(newObj);
//		List properties = newObj.getInstanceProperties();
		if (features != null) {
			for (int i = 0; i < features.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) features.get(i);
				Object value = newObj.eGet(feature);

				if ( value instanceof List) {
					
					// fixing the feature value may cause the list to change
					// iterate on a new copy to avoid
					// ConcurrentModificationException
					for (Iterator it= new ArrayList(((List)value)).iterator(); it.hasNext(); ) {
						Object o = it.next();
						fixNewElementFeatureValue(newObj, feature, o);
					}
				} else {
					fixNewElementFeatureValue(newObj, feature, value);
				}
			}
		}	
	}
	
	
	private void fixDiagram(DiagramElement newObj) {		

		if ( processedNewElements.contains(newObj) ) {
			return;
		}
		
		processedNewElements.add(newObj);
		
		if ( debug ) {
			System.out.println("Fixing diagram element " + LibraryUtil.getTypeName(newObj)); //$NON-NLS-1$
		}
		
		List features = LibraryUtil.getStructuralFeatures(newObj);
//		List properties = newObj.getInstanceProperties();
		if (features != null) {
			for (int i = 0; i < features.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) features.get(i);
				Object value = newObj.eGet(feature);

				if ( value instanceof List) {
					
					// fixing the feature value may cause the list to change
					// iterate on a new copy to avoid
					// ConcurrentModificationException
					for (Iterator it= new ArrayList(((List)value)).iterator(); it.hasNext(); ) {
						Object o = it.next();
						if ( o instanceof MethodElement ) {
							if ( feature == UmaPackage.eINSTANCE.getUMASemanticModelBridge_Element() ) {
								fixNewElementFeatureValue(newObj, feature, o);
							} else if ( (o instanceof DiagramElement) ) {
								fixDiagram((DiagramElement)o);
							} 
						}
					}
				} else if ( value instanceof MethodElement ) {
					if ( feature == UmaPackage.eINSTANCE.getUMASemanticModelBridge_Element() ) {
						fixNewElementFeatureValue(newObj, feature, value);
					} else if ( (value instanceof DiagramElement) ) {
						fixDiagram((DiagramElement)value);
					} 
				}
			}
		}	
	}
	
	/**
	 * check if the value is an old element in the base, if yes, replace it with
	 * the old one if it's new, iterate it's feature value
	 * 
	 * @param feature
	 * @param obj
	 */
	private void fixNewElementFeatureValue(MethodElement element, EStructuralFeature feature, Object obj) {
		if ( !(obj instanceof MethodElement) ) {
			return;
		}
		
		if ( debug ) {
			System.out.println("fixing element feature value " + LibraryUtil.getTypeName(element) + ", feature=" + feature.getName()); //$NON-NLS-1$ //$NON-NLS-2$
		}

		boolean oldNotify = element.eDeliver();
		try
		{
			element.eSetDeliver(false);
			
			MethodElement newObj = (MethodElement)obj;
			MethodElement oldObj = getReplaced(newObj.getGuid());
			if ( oldObj == null ) {
				// get existing element, for example, the global packages in the
				// configuration feature
				oldObj = diffMgr.getExistingElement(newObj.getGuid());
			}
			
			if ( oldObj == null ) {
				// it's a new one
				fixNewElementReferences(newObj);
			} else {
				
				try {
					// replace the newObj with the oldObj
					EcoreUtil.replace(element, feature, newObj, oldObj); 
				}
				catch (Exception ex) {
					// if replace failed, remove the feature
					EcoreUtil.remove(element, feature, newObj); 
					if (debug ) {
						System.out.println("Replaceing feature value failed for element ["  //$NON-NLS-1$
								+ LibraryUtil.getTypeName(element) + "], feature ["  //$NON-NLS-1$
								+ feature.getName() + "], value="  //$NON-NLS-1$
								+ newObj + ". The feature value is removed. "); //$NON-NLS-1$
						
					}
				}
			}	
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		finally
		{
			element.eSetDeliver(oldNotify);
		}
	}
	
	private boolean canReset(MethodElement e) {
		boolean reset = false;
		
		// an element can be reset if you are sure that no other element(s)
		// reference to it
		// reset elements may have references to other elements in the importing
		// library, that needs to be fixed later
		
		// for anything contained by ContentDescription, reset it
		if ( e == null /* || e.eContainer() instanceof ContentDescription */
				|| e instanceof DiagramElement) {
			reset = true;
		}
				
		return reset;
	}

	private boolean canReset(EStructuralFeature feature) {
		// for anything contained by ContentDescription, reset it
		// no don't reset the sections since it will cause the one in the
		// importing library removed
		// which caused problem for TaskDescription where the same feature
		// (Steps) can't find the steps from the importing library
		// which then will treat the steps in the base library being deteted
// if ( feature == UmaPackage.eINSTANCE.getContentDescription_Sections()) {
// return true;
// }
		return false;
	}

	private boolean canIgnore(EStructuralFeature feature) {
		// don't reset the plugin lock status
		if ( feature == UmaPackage.eINSTANCE.getMethodPlugin_UserChangeable()) {
			return true;
		}

		// 146144 - Import Configuration: some unchange elements disappear in authoring after import
		// this is caused by a bug in ArtifactImpl, when setContainerArtifact to null, 
		//  it set the eContainer to null, if the eContainer is a content package, 
		// the artifact is removed from the package
		//  this bug will be fixed in M4. 
		// for now, ignore this feature since this is an opposite feature, we don't need to handle it	
		if ( feature == UmaPackage.eINSTANCE.getArtifact_ContainerArtifact() ) {
			return true;
		}
		return false;
	}
	
	private boolean isReplaced(MethodElement oldObj) {
		return replacedElementMap.containsKey(oldObj.getGuid());
	}

	private void setReplaced(MethodElement oldObj) {
		String guid = oldObj.getGuid();
		if ( !replacedElementMap.containsKey(guid) ) {
			replacedElementMap.put(guid, oldObj);
			setModified(oldObj);
		}
	}
	
	/**
	 * get the old element been replaced
	 * 
	 * @param oldObj
	 * @return
	 */
	private MethodElement getReplaced(String guid) {
		return (MethodElement)replacedElementMap.get(guid);
	}
	
	/**
	 * when new elements are added into the library, the associated resource
	 * files must be copied over as well
	 * 
	 * @param newObj
	 *            MethodElement
	 */
	private void copyNewElementResources(MethodElement newObj) {
		
//		List properties = newObj.getInstanceProperties();
//		if (properties != null) {
//			for (int i = 0; i < properties.size(); i++) {
//				EStructuralFeature feature = (EStructuralFeature) properties.get(i);
//				Object value = newObj.eGet(feature);
//				if ( value instanceof URI ) {
//					resScanner.copyResource(((URI)value).getPath());
//				} else if ( value instanceof String ) {
//					resScanner.scan(newObj, (String)value);
//				}
//			}
//		}
//		
//		for ( Iterator it = newObj.eContents().iterator(); it.hasNext(); ) {
//			Object o = it.next();
//			if ( o instanceof MethodElement ) {
//				copyNewElementResources((MethodElement)o);
//			}
//		}
		
		scanResources(newObj, true);
	}
	
	private void logNewElement(MethodElement newObj) {
		
		// make sure the element is not in the original library
		// since we have the guid-element map build up in the diff manager,
		// check there
		if ( !newElements.contains(newObj) && diffMgr.getExistingElement(newObj.getGuid()) == null) {
			newElements.add(newObj);
			copyNewElementResources(newObj);
			setModified(newObj);
		}
	}
	
	private void logResetElement(MethodElement newObj) {
		if ( !newElements.contains(newObj) ) {
			newElements.add(newObj);
			setModified(newObj);
		}
	}

	private void logNewResource(Resource res ) {
		if ( res != null ) {
			
			// mark the resource as dirty so that we can save it again
			// the first save may lose cross references 
			res.setModified(true);
			String file = res.getURI().toFileString();
			if ( !newResources.contains(file) ) {
				newResources.add(file);
			}
		}
	}
	
	private void logRemovedElements(List items) {
		
		if ( items == null || items.size() == 0 ) {
			return;
		}
		
		// removed elements can be removed from any feature
		// check if the element's container is null
		// if is, then the element is deleted and the resource should be deleted
		// as well
		for (Iterator it = items.iterator(); it.hasNext(); ) {
			MethodElement e = (MethodElement)it.next();
			if ( (e.eContainer() == null) && !deletedElements.contains(e) ) {			
				deletedElements.add(e);
			}			
		}
	}
	
	private void setModified(EObject obj) {
		if ( obj != null ) {
			Resource res = obj.eResource();
			if ( res != null ) {
				if ( !res.isModified() ) {
					res.setModified(true);				
				}
// } else {
// System.out.println("No resource for " + obj);
				
				if (debug && res.isModified() ) {
					System.out.println("Modified: " + res.getURI().toFileString()); //$NON-NLS-1$
				}

			}
		}
	}

	private List getModifiedResources(MethodLibrary lib) {
		
		// avoid the newly added element resources
		List modifiedList = new ArrayList();
		Resource res = lib.eResource();
		if ( res != null ) {
			ResourceSet resSet = res.getResourceSet();
			for ( Iterator it = resSet.getResources().iterator(); it.hasNext(); ) {
				res = (Resource) it.next();
				if ( res != null && res.isModified() ) {
					String file = res.getURI().toFileString();
					if ( newResources.contains(file) ) {
						continue;
					}
					
					if ( debug ) {
						System.out.println("Resource modified: " + file); //$NON-NLS-1$
					}		
					modifiedList.add(file);
				}
			}
		}
		return modifiedList;
	}

	// clear resources for deleted elements
	private void deleteResoruces() {
		if ( deletedElements.size() == 0 ) {
			return;
		}
		
		IFileManager fileMgr = Services.getFileManager();

		for (Iterator it = deletedElements.iterator(); it.hasNext(); ) {
			MethodElement e = (MethodElement)it.next();
			
			EObject obj = null;
			if ( e instanceof DescribableElement ) {
				obj = ((DescribableElement)e).getPresentation();
			} else if ( e instanceof ContentDescription ) {
				obj = e;
			}
			if ( obj != null ) {
				Resource res = obj.eResource();
				if ( res != null ) {
					String file = res.getURI().toFileString();
					if ( debug ) {
						System.out.println("deleting resource: " + file); //$NON-NLS-1$
					}
					
					if ( !fileMgr.delete(file) ) {
						if ( debug ) {
							System.out.println("unable to delete file: " + file); //$NON-NLS-1$
						}
					}
				}								
			}
		}
	}

	
	public class ElementListDiff {

		List newItems = new ArrayList();
		List deletedItems = new ArrayList();
		
		// use LinkedHashMap to reserve the order of the values
		Map oldNewMap = new LinkedHashMap();

		// with the old and new list of MethodElements,
		// find the common ones, the deleted ones, and the new ones
		public ElementListDiff(List oldList, List newList) {
			// Map oldListGuidMap = getGuidMap(oldList);
			Map newListGuidMap = getGuidMap(newList);

			newItems.addAll(newList);

			for (Iterator it = oldList.iterator(); it.hasNext(); ) {
				MethodElement oldObj = (MethodElement)it.next();
				String guid = oldObj.getGuid();
				Object newObj = newListGuidMap.get(guid);
				if ( newObj != null ) {
					oldNewMap.put(oldObj, newObj);
					newItems.remove(newObj);
				}
				else
				{
					// it's been deleted
					deletedItems.add(oldObj);
				}
			}
		}

		private Map getGuidMap(List items) {
			Map m = new HashMap();
			for (Iterator it= items.iterator(); it.hasNext(); ) {
				MethodElement e = (MethodElement)it.next();
				m.put(e.getGuid(), e);
			}

			return m;
		}
	}	
	
	/**
	 * Handles name replacement.
	 */
	public static void handleNameReplace(Map renameElementMap) {
		Iterator it = renameElementMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			Object[] val = (Object[])entry.getValue();
			
			MethodElement element = (MethodElement) val[0];
			String newName = val.length == 4 ? element.getGuid() : (String) val[1];
			rename(element, newName);
			if (val.length == 4) {
				element = (MethodElement) val[2];
				newName = (String) val[3];
				rename(element, newName);
				
				element = (MethodElement) val[0];
				newName = (String) val[1];
				rename(element, newName);
			}
		}
		
		//Make resouces dirty again, as rename process would mark resouce un-modified
		it = renameElementMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			Object[] val = (Object[])entry.getValue();			
			MethodElement element = (MethodElement) val[0];
			element.eResource().setModified(true);
		}
	}
	
	private static void rename(MethodElement element, String newName) {
		if (newName.equals(element.getName())) {
			return;
		}
		if (element instanceof ContentDescription || element.eResource() == null) {
			element.setName(newName);
			if (element instanceof ProcessComponent) {
				Process proc = ((ProcessComponent) element)
						.getProcess();
				proc.setName(newName);
			}
		} else {
			LibraryView.runRename(element, newName);
		}
	}
		
	private void registerSetElement(MethodElement element, EStructuralFeature feature, Object newValue) {
		String guid0 = ((MethodElement)newValue).getGuid();
		String guid1 = element.getGuid();
		Object[] val = new Object[3];
		val[0] = feature;
		val[1] = newValue;
		val[2] = element;
		if (setElementMap == null) {
			setElementMap = new HashMap();
		}
		setElementMap.put(element.getName() + guid0 + guid1, val);
	}
	
	private void handleSetElements() {
		if (setElementMap == null) {
			return;
		}
		for (Iterator it = setElementMap.entrySet().iterator(); it.hasNext();) {
			Map.Entry entry = (Map.Entry) it.next();
			Object[] val = (Object[])entry.getValue();
			EStructuralFeature feature = (EStructuralFeature) val[0];
			MethodElement newValue = (MethodElement) val[1];
			MethodElement element = (MethodElement) val[2];
			String guid = newValue.getGuid();
			MethodElement mergedValue = (MethodElement) replacedElementMap.get(guid);
			if (mergedValue != null && mergedValue != newValue) {
				element.eSet(feature, mergedValue);
			}			
		}
	}

	/**
	 * Ensures unique name.
	 */
	public static void ensureUniqueName(EObject owner, MethodElement newObj, Map renameElementMap) {
		if (owner == null) {
			return;
		}
		Class cls = newObj.getClass();
		Map nameMap = new HashMap();
		for (int i=0; i < owner.eContents().size(); i++) {
			Object oldObj = owner.eContents().get(i);
			if (oldObj.getClass() == cls && oldObj != newObj) {
				MethodElement oldElem = (MethodElement) oldObj;
				nameMap.put(oldElem.getName(), oldElem);
			}
		}
		String name = newObj.getName();
		String renamed = name;
		while (nameMap.containsKey(renamed)) {
			renamed += "_renamed"; //$NON-NLS-1$
		}
		if (renamed != name) {
			newObj.setName(renamed);
			
			Object[] entryVal = new Object[4];
			entryVal[0] = newObj;
			entryVal[1] = name;
			entryVal[2] = nameMap.get(name);
			entryVal[3] = renamed;
			renameElementMap.put(newObj.getGuid(), entryVal);			
		}
	}
	
	/**
	 * Ensures unique name for existing element.
	 */
	public static void ensureUniqueNameForExistingElement(MethodElement element, String oldName, String newName, Map renameElementMap) {
		EObject elementOwner = element.eContainer();					
		if (elementOwner != null) {
			element.setName(newName);
			ensureUniqueName(elementOwner, element, renameElementMap);
			if (!element.getName().equals(newName)) {	//if handled then return
				return;
			}			
			element.setName(oldName);
		}			
		Object[] entryVal = new Object[2];
		entryVal[0] = element;
		entryVal[1] = newName;
		renameElementMap.put(element.getGuid(), entryVal);
	}

	private void checkModifiedFiles() {
		final List modifiedFiles = getModifiedResources(baseLibrary);
		modifiedFiles.addAll(resScanner.getFilesTobeReplaced());
		modifiedFiles.addAll(diagramHandler.getModifiedFiles());

		SafeUpdateController.syncExec(new Runnable() {
			public void run() {
				fileCheckedOutStatus = FileModifyChecker.checkModify(modifiedFiles);
			}
		});
	}

	private List unlockPlugins() {

		List pluginIds = new ArrayList();
		
		Map<String, MethodPlugin> map = new HashMap<String, MethodPlugin>();
		Map<String, MethodPlugin> guidMap = new HashMap<String, MethodPlugin>();
		List<MethodPlugin> basePlugins = LibraryService.getInstance().getCurrentMethodLibrary()
											.getMethodPlugins();
		for (int i = 0; i < basePlugins.size(); i++) {
			MethodPlugin plugin = basePlugins.get(i);
			map.put(plugin.getName(), plugin);
			guidMap.put(plugin.getGuid(), plugin);
		}
		
		if (map.isEmpty()) {
			return pluginIds;
		}
		
		List fileNameToCheck = new ArrayList();
		List<MethodPlugin> importPlugins = importingLibrary.getMethodPlugins();
		for (int i = 0; i < importPlugins.size(); i++) {
			MethodPlugin plugin = importPlugins.get(i);
			String name = plugin.getName();
			String guid = plugin.getGuid();
			
			MethodPlugin basePlugin0 = guidMap.get(guid);
			if (basePlugin0 != null) {
				String name0 = basePlugin0.getName();
				if (! name0.equals(name)) {
					renamePluginMap.put(name0, name);
				}
			}
			
			MethodPlugin basePlugin = map.get(name);
			boolean toAdd = false;
			if (basePlugin != null && ! basePlugin.getGuid().equals(guid)
					&& ! basePlugin.getUserChangeable()) {
				toAdd = true;
			} else {
				basePlugin = guidMap.get(guid);
				if (basePlugin != null /*&& ! basePlugin.getName().equals(name)*/
						&& ! basePlugin.getUserChangeable()) {
					toAdd = true;
				} 
			}
			
			if (toAdd){				
				pluginIds.add(basePlugin.getGuid());
				basePlugin.setUserChangeable(new Boolean(true));
				Resource res = basePlugin.eResource();
				if (res != null && res.getURI() != null) {
					String fileName = res.getURI().toFileString();
					fileNameToCheck.add(fileName);
				}
			}
		}	
		
		if (fileNameToCheck.size() > 0) {
			final List modifiedFiles = fileNameToCheck;	
			SafeUpdateController.syncExec(new Runnable() {
				public void run() {
					fileCheckedOutStatus = FileModifyChecker.checkModify(modifiedFiles);
				}
			});
		}
		
		return pluginIds;
	}

	/**
	 * @param unlockedPlugins
	 */
	public static void lockUnlockedPlugins(List unlockedPlugins) {
		List plugins = LibraryService.getInstance().getCurrentMethodLibrary()
				.getMethodPlugins();
		for (Iterator it = plugins.iterator(); it.hasNext();) {
			MethodPlugin plugin = (MethodPlugin) it.next();
			if (unlockedPlugins.contains(plugin.getGuid())) {
				plugin.setUserChangeable(new Boolean(false));
			}
		}
	}
	
	private void logNewElementUnderExistingPlugin(MethodElement newObj) {
		ILibraryResourceManager libResMgr = ResourceHelper.getResourceMgr(newObj);
		String pluginPath = libResMgr.getPhysicalPluginPath(newObj);
		if (pluginPath != null) {
			logNewElement(newObj);
		}
	}
	
}