//------------------------------------------------------------------------------
// 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.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;				
				
				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(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(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);
		}
	}
	
}