//------------------------------------------------------------------------------
// 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.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.serviceability.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.edit.util.TngUtil;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.services.IFileManager;
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.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.UmaPackage;


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

	private Map renameElementMap = new HashMap();
	private Map setElementMap = null;

	private LibraryDiffManager diffMgr;
	private ElementDiffTree rootTree;

	//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));
			
		diagramHandler = new DiagramHandler(
				LibraryUtil.getLibraryRootPath(importingLibrary), 
				LibraryUtil.getLibraryRootPath(baseLibrary));
	}
		
	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 {

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

		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$
			}
			
			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 properties = oldObj.getInstanceProperties();
		if (properties != null) {
			for (int i = 0; i < properties.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) properties.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 properties = oldObj.getInstanceProperties();
		if (properties != null) {
			for (int i = 0; i < properties.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) properties.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 properties = oldObj.getInstanceProperties();
		if (properties != null) {
			for (int i = 0; i < properties.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) properties.get(i);
				if ( feature == UmaPackage.eINSTANCE.getMethodPackage_ChildPackages() )
				{
					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() );
					}
				}
				
				// 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 properties = oldObj.getInstanceProperties();
		if (properties != null) {
			for (int i = 0; i < properties.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) properties.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);
				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);							
							} 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);
					}
					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);
						}
					}
				}
			}
			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 scanResources(MethodElement element, boolean recursive) {

		if ( element == null ) {
			return;
		}
		
		List properties = element.getInstanceProperties();
		if (properties != null) {
			for (int i = 0; i < properties.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) properties.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
				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 ) {
			resScanner.copyResource ( ((URI)newValue).getPath());
		}

	}
	
	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);
					LibraryUtil.saveLibrary((MethodLibrary)owner, false, false);
				}
								
			} else if (newObj instanceof MethodConfiguration ) {
				checkModifiedFiles();				
				error = ! fileCheckedOutStatus.isOK();
				if (!error) {
					((MethodLibrary)owner).getPredefinedConfigurations().add(newObj);
					LibraryUtil.saveLibrary((MethodLibrary)owner, false, 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 msg = "can't add " + LibraryUtil.getTypeName(newObj) //$NON-NLS-1$
			+ " to " + LibraryUtil.getTypeName((MethodPackage)owner); //$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));
				}
				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(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 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 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 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 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$
		}

		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 [" 
								+ LibraryUtil.getTypeName(element) + "], feature [" 
								+ feature.getName() + "], value=" 
								+ newObj + ". The feature value is removed. ");
						
					}
				}
			}	
		}
		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());
				}

			}
		}
	}

	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);
					}		
					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);
					}
					
					if ( !fileMgr.delete(file) ) {
						if ( debug ) {
							System.out.println("unable to delete file: " + file);
						}
					}
				}								
			}
		}
	}

	
	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";
		}
		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);
			}
		});
	}

	
}