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

import java.io.File;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.sdo.EDataObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.dataexchange.importing.LibraryService;
import org.eclipse.epf.dataexchange.util.ContentProcessor;
import org.eclipse.epf.dataexchange.util.ILogger;
import org.eclipse.epf.export.xml.services.FeatureManager;
import org.eclipse.epf.export.xml.services.XMLLibrary;
import org.eclipse.epf.importing.xml.ImportXMLPlugin;
import org.eclipse.epf.importing.xml.ImportXMLResources;
import org.eclipse.epf.library.edit.util.MethodElementPropertyHelper;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.persistence.MultiFileSaveUtil;
import org.eclipse.epf.services.IFileManager;
import org.eclipse.epf.services.Services;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.CapabilityPattern;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.Discipline;
import org.eclipse.epf.uma.DisciplineGrouping;
import org.eclipse.epf.uma.Domain;
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.ProcessComponent;
import org.eclipse.epf.uma.ProcessElement;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.RoleSet;
import org.eclipse.epf.uma.RoleSetGrouping;
import org.eclipse.epf.uma.Section;
import org.eclipse.epf.uma.Tool;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkOrderType;
import org.eclipse.epf.uma.WorkProductType;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.epf.xml.uma.TaskDescriptor;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.text.SimpleDateFormat;

/**
 * UmaLibrary represents a method library and provide methods to create elements
 * and set attributes and feature values
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public class UmaLibrary {

	private boolean debug = ImportXMLPlugin.getDefault().isDebugging();

	private boolean overwrite = false;
	
	private int mergeLevel = 0;
	
	private ILogger logger;

	private ContentProcessor contentProc = null;
	
	private Map newElementsMap = new HashMap();
	
	private Map renameElementMap;

	// map of created elements, guid - EDataObject
	Map elementsMap = new HashMap();

	// keep the source element ids so we can determine the elements that are not in the xml source library
	// this is needed for deleting un-needed elements
	// 154149 - allow package level merging for xml import
	HashSet sourceElementIDs = new HashSet();
	
	/**
	 * The constructor.
	 * @param contentProc
	 * @param logger
	 * @param overwrite
	 */
	public UmaLibrary(Map renameElementMap, ContentProcessor contentProc, ILogger logger, boolean overwrite) {
		this.renameElementMap = renameElementMap;
		this.logger = logger;
		this.contentProc = contentProc;
		this.overwrite = overwrite;

		buildElementsMap();
	}

	/**
	 * @return the current library as the root object.
	 */
	public MethodLibrary getRoot() {
		return org.eclipse.epf.library.LibraryService.getInstance()
				.getCurrentMethodLibrary();
	}

	private void buildElementsMap() {
		// build the elements map for easy operation

		elementsMap.clear();
		elementsMap.put(getRoot().getGuid(), getRoot());
		TreeIterator it = getRoot().eAllContents();
		while (it.hasNext()) {
			Object e = it.next();
			if (e instanceof MethodElement) {
				elementsMap.put(((MethodElement) e).getGuid(), e);
			}
		}
	}

	/**
	 * Creates a content catergory.
	 * @param pluginId
	 * @param xmlEClassName
	 * @param xmlElementType
	 * @param id
	 * @return
	 */
	public EDataObject createContentCategory(String pluginId,
			String xmlEClassName, String xmlElementType, String id) {

		setSourceId(id);
		
		// make sure the same object created only once
		EDataObject obj = getElement(id);
		if (obj != null) {
			return obj;
		}

		MethodPlugin plugin = (MethodPlugin) getElement(pluginId);

		EClass objClass = FeatureManager.INSTANCE.getRmcEClass(xmlEClassName);
		if (objClass == null) {
			logger.logWarning(NLS.bind(ImportXMLResources.library_error_no_eclass, xmlEClassName));
			return null;
		}

		obj = (EDataObject) EcoreUtil.create(objClass);
		setElement(id, obj);

		ContentPackage rootPkg = (ContentPackage) getRootPackage(plugin, obj);
		rootPkg.getContentElements().add((ContentCategory)obj);
		return obj;
	}

	/**
	 * Gets the root package
	 * @param plugin
	 * @param obj
	 * @return
	 */
	public MethodPackage getRootPackage(MethodPlugin plugin, Object obj) {

		String[] path = null;
		if (obj instanceof CustomCategory) {
			path = ModelStructure.DEFAULT.customCategoryPath;
		} else if (obj instanceof Discipline
				|| obj instanceof DisciplineGrouping) {
			path = ModelStructure.DEFAULT.disciplineDefinitionPath;
		} else if (obj instanceof Domain) {
			path = ModelStructure.DEFAULT.domainPath;
		} else if (obj instanceof RoleSet || obj instanceof RoleSetGrouping) {
			path = ModelStructure.DEFAULT.roleSetPath;
		} else if (obj instanceof Tool) {
			path = ModelStructure.DEFAULT.toolPath;
		} else if (obj instanceof WorkProductType) {
			path = ModelStructure.DEFAULT.workProductTypePath;
		}

		if (path != null) {
			return UmaUtil.findMethodPackage(plugin, path);
		} else {
			logger.logWarning(NLS.bind(ImportXMLResources.library_no_package, obj)); 
		}

		return null;
	}

	/**
	 * Creates a method plugin.
	 * @param id
	 * @param name
	 * @return
	 * @throws Exception
	 */
	public EDataObject createMethodPlugin(String id, String name)
			throws Exception {
		
		// make sure the same object created only once
		EDataObject obj = getElement(id);
		boolean isOld = obj != null;
		if (obj == null) {
			Map options = new HashMap();
			options.put("renameElementMap", renameElementMap);//$NON-NLS-1$
			obj = LibraryService.INSTANCE.createPlugin(name, id, options);

			setElement(id, obj);
		}

		// make sure the system packages are included
		setSourceId(id);
		List pkgs = TngUtil.getAllSystemPackages((MethodPlugin)obj);
		for (Iterator it = pkgs.iterator(); it.hasNext(); ) {
			MethodPackage pkg = (MethodPackage)it.next();
			setSourceId(pkg.getGuid());
			if (!isOld) {
				newElementsMap.put(pkg.getGuid(), pkg);
			}
		}
		
		return obj;
	}

	/**
	 * Gets content's root package.
	 * @param plugin
	 * @return
	 */
	public EDataObject getContentRootPackage(EDataObject plugin) {
		if (!(plugin instanceof MethodPlugin)) {
			return null;
		}
		return UmaUtil.findMethodPackage((MethodPlugin) plugin,
				ModelStructure.DEFAULT.coreContentPath);
	}

	/**
	 * Gets capability pattern' root package.
	 * @param plugin
	 * @return
	 */
	public EDataObject getCapabilityPatternRootPackage(EDataObject plugin) {
		if (!(plugin instanceof MethodPlugin)) {
			return null;
		}
		return UmaUtil.findMethodPackage((MethodPlugin) plugin,
				ModelStructure.DEFAULT.capabilityPatternPath);
	}

	/**
	 * Gets delivery process' root package.
	 * @param plugin
	 * @return
	 */
	public EDataObject getDeliveryProcessRootPackage(EDataObject plugin) {
		if (!(plugin instanceof MethodPlugin)) {
			return null;
		}
		return UmaUtil.findMethodPackage((MethodPlugin) plugin,
				ModelStructure.DEFAULT.deliveryProcessPath);
	}

//	public EDataObject getProcessContributionRootPackage(EDataObject plugin) {
//		if (!(plugin instanceof MethodPlugin)) {
//			return null;
//		}
//		return UmaUtil.findMethodPackage((MethodPlugin) plugin,
//				ModelStructure.DEFAULT.processContributionPath);
//	}

	/**
	 * Creates an element.
	 * @param container
	 * @param xmlFeatureName
	 * @param xmlEClassName
	 * @param xmlElementType
	 * @param id
	 * @return
	 */
	public EDataObject createElement(EDataObject container,
			String xmlFeatureName, String xmlEClassName, String xmlElementType,
			String id) {

		setSourceId(id);

		// make sure the same object created only once
		EDataObject obj = getElement(id);
		if (obj != null) {
			if (obj instanceof Activity) {
				EObject eobj = obj.eContainer();
				if (eobj instanceof ProcessPackage) {
					ProcessPackage p = (ProcessPackage) eobj;
					setSourceId(p.getGuid());
				}
			}
			return obj;
		}

		// if ( obj instanceof MethodPlugin ) {
		// return getElement(id);
		// }

		// // this is an easier way, test it,
		// // does not work since feature.getEType() returns the base element
		// type, not the extended one
		// // for example, it returns MethodPackage instead of ProcessPackage or
		// ContentPackage
		// // so we need to make our own map
		// EClassifier c = feature.getEType();

		EClass objClass = FeatureManager.INSTANCE.getRmcEClass(xmlEClassName);
		if (objClass == null) {
			logger.logWarning(NLS.bind(ImportXMLResources.library_error_no_eclass, xmlEClassName)); 
			return null;
		}

		obj = (EDataObject) EcoreUtil.create(objClass);	

		if (obj instanceof WorkOrder) {
			// WorkOrder is not a method element in xml uma, need to create it
			// with a guid
			//id = EcoreUtil.generateUUID();

			// also need to add the element into the container of the owner
			((ProcessPackage) container.eContainer()).getProcessElements().add(
					(WorkOrder)obj);
		}

		setElement(id, obj);

		try {
			if (container instanceof MethodPlugin) {
				MethodPlugin plugin = (MethodPlugin) container;
				// need special handling for new plugin
				if (obj instanceof ContentPackage) {
					// content package and owner is Plugin, goto the root
					// content package
					MethodPackage pkg_core_content = UmaUtil.findMethodPackage(
							plugin, ModelStructure.DEFAULT.coreContentPath);
					pkg_core_content.getChildPackages().add((ContentPackage)obj);
				} else if (obj instanceof ProcessComponent) {
					MethodPackage pkg_cp = UmaUtil.findMethodPackage(plugin,
							ModelStructure.DEFAULT.capabilityPatternPath);
					pkg_cp.getChildPackages().add((ProcessComponent)obj);

				} else if (obj instanceof ProcessPackage) {
					// this is a root process package
					// put into the root delivery processes package
					MethodPackage pkg_dp = UmaUtil.findMethodPackage(plugin,
							ModelStructure.DEFAULT.deliveryProcessPath);
					pkg_dp.getChildPackages().add((ProcessPackage)obj);
				}
			} else {

				EStructuralFeature feature = FeatureManager.INSTANCE
						.getRmcFeature(container.eClass(), xmlFeatureName);
				if (feature == null) {
					return null;
				}

				if ((container instanceof Activity)
						&& feature == UmaPackage.eINSTANCE
								.getActivity_BreakdownElements()
						&& obj instanceof BreakdownElement) {

					// the container needs to be a process package
					EObject pkg = container;
					while ((pkg != null) && !(pkg instanceof ProcessPackage)) {
						pkg = pkg.eContainer();
					}

					// if the object is an activity, create a package for it and
					// all it's breakdown elements
					if ((obj instanceof Activity)) {
						List childPkgs = ((ProcessPackage) pkg)
								.getChildPackages();
						ProcessPackage pp = null;
						if (true || childPkgs.size() == 0) {	//158363: always create a package for act
							pp = UmaFactory.eINSTANCE.createProcessPackage();
							pp.setName(((MethodElement) container).getName());
							setElement(EcoreUtil.generateUUID(), pp);
							setSourceId(pp.getGuid());
							childPkgs.add(pp);
						} else {
							pp = (ProcessPackage) childPkgs.get(0);
						}

						pkg = pp;
					}

					((ProcessPackage) pkg).getProcessElements().add((ProcessElement)obj);
				}

				// note: all element references are string type (id)
				// package references are object references
				if (feature.isMany()) {
					List values = (List) container.eGet(feature);
					values.add(obj);
				} else {
					container.eSet(feature, obj);
				}
			}				
		} catch (RuntimeException e) {
			logger.logWarning(NLS.bind(ImportXMLResources.library_error_create_element, e.getMessage()));
			// e.printStackTrace();
		}

		return obj;
	}

	private void setElement(String guid, EDataObject obj) {
		// addElementToContainer(container, obj);
				
		if (!elementsMap.containsKey(guid)) {

			if (obj instanceof MethodElement) {
				((MethodElement) obj).setGuid(guid);
			}

			elementsMap.put(guid, obj);
					
			setDirty(obj);
			newElementsMap.put(guid, obj);
		}
	}

	private void setSourceId(String id) {
		// 154149 - allow package level merging for xml import
		if ( !sourceElementIDs.contains(id) ) {
			sourceElementIDs.add(id);
		}
	}
	
	private void setDirty(EObject obj) {
		// mark the resource as dirty
		Resource res = obj.eResource();
		if ( res != null && !res.isModified() ) {
			res.setModified(true);
		}
	}
	
	/**
	 * Gets element given the guid.
	 * @param guid
	 * @return
	 */
	public EDataObject getElement(String guid) {
		return (EDataObject) elementsMap.get(guid);
	}

	private Date createDate(String dateStr) {
		dateStr = dateStr.replace('T', ' ');
		SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //$NON-NLS-1$
		return f.parse(dateStr, new ParsePosition(0));

	}

	private String getString(Object obj) {
		String str = ""; //$NON-NLS-1$
		if (obj instanceof MethodElement) {
			str = LibraryUtil.getTypeName((MethodElement) obj);
		} else if (obj != null) {
			str = obj.toString();
		}

		return str;
	}

	/**
	 * Sets attribute feature value.
	 * @param obj
	 * @param featureName
	 * @param value
	 * @throws Exception
	 */
	public void setAtributeFeatureValue(EDataObject obj, String featureName,
			Object value) throws Exception {
		boolean oldNotify = obj.eDeliver();
		obj.eSetDeliver(false);
		setAtributeFeatureValue_(obj, featureName, value);
		obj.eSetDeliver(oldNotify);
	}
	
	private void setAtributeFeatureValue_(EDataObject obj, String featureName,
			Object value) throws Exception {
		if (obj == null || featureName == null || value == null) {
			return;
		}
		
		if (value instanceof List || value instanceof EDataObject) {
			if (featureName.equals("methodElementProperty")) {		//$NON-NLS-1$
				setMepFeatureValue(obj, featureName, value);
				return;
			}
			throw new Exception(NLS.bind(ImportXMLResources.library_error_set_attribute_2, value)); 
		}

		// find the feature and set the value
		EStructuralFeature feature = FeatureManager.INSTANCE.getRmcFeature(obj
				.eClass(), featureName);
		if (feature == null) {
			Object[] paras = new Object[] { getString(obj), featureName, value };
			logger.logWarning(NLS.bind(ImportXMLResources.library_error_set_attribute, paras) + obj); 
			return;
		} 
		
		setDirty(obj);

		// 158688 - Missing template files in exported xml library
		// process the attachment url
		if ( feature == UmaPackage.eINSTANCE.getGuidanceDescription_Attachments() ) {
			if ( value != null ) {
				value = contentProc.resolveAttachmentResources(obj, value.toString().trim());
			}
			obj.eSet(feature, value);
		}
		
		else if (feature instanceof EReference && value instanceof String) {
			// if the uma feature is a reference feature
			// but the xml feature is an attribute
			// the attribute value must be a guid
			Object e = getElement((String) value);
			if (e != null) {
				if (feature.isMany()) {
					((List) obj.eGet(feature)).add(e);
				} else {
					obj.eSet(feature, e);
				}
			} else {
				Object[] paras = new Object[] { getString(obj),
						feature.getName(), value };
				String msg = NLS.bind(ImportXMLResources.library_error_set_attribute, paras); 
				logger.logWarning(msg);
			}
		} else if (feature instanceof EAttribute) {
			try {
				if (feature.getName().equals("variabilityType")) { //$NON-NLS-1$
					value = VariabilityType.get(value.toString());
				} else if (feature.getName().equals("linkType")) { //$NON-NLS-1$
					value = WorkOrderType.get(value.toString());
				} else if (feature == UmaPackage.eINSTANCE
						.getMethodUnit_ChangeDate()) {
					// convert java.util.Date to xml Date
					value = createDate(value.toString());
				} else if (feature.getName().equals("nodeicon") //$NON-NLS-1$
						|| feature.getName().equals("shapeicon")) { //$NON-NLS-1$
					MethodPlugin tgtPlugin = UmaUtil.getMethodPlugin((MethodElement) obj);
					int ix = tgtPlugin.getName().length() + 1;
										
					value = new java.net.URI(value.toString().substring(ix));

					// need to copy the resource file to the target library
					contentProc.copyResource(((java.net.URI) value).getPath(), obj, tgtPlugin);
				} else if ((contentProc != null)
						&& (obj instanceof MethodElement)
						&& (value instanceof String)) {
					value = contentProc.resolveResourceFiles(
							(MethodElement) obj, (String) value);
				}
				obj.eSet(feature, value);
			} catch (RuntimeException e) {
				Object[] paras = new Object[] { getString(obj), featureName,
						value };
				logger.logError(NLS.bind(ImportXMLResources.library_error_set_attribute, paras), e); 
				// e.printStackTrace();
			}
		} else {
			Object[] paras = new Object[] { getString(obj), featureName, value };
			logger.logWarning(NLS.bind(ImportXMLResources.library_error_set_attribute_3, paras)); 
		}

	}

	private void setMepFeatureValue(EDataObject obj, String featureName, Object value) {
		List srcList = (List) value;
		int sz = srcList == null ? 0 : srcList.size();		
		EStructuralFeature feature = FeatureManager.INSTANCE.getRmcFeature(obj
				.eClass(), featureName);
		List tgtList = (List) obj.eGet(feature);
		int tsz = tgtList == null ? 0 : tgtList.size();

		//Source list is empty
		if (sz == 0) {
			if (tsz == 0) {
				return;
			}
			tgtList.removeAll(tgtList);
			setDirty(obj);
			return;
		}
		
		//Soruce and target are potentially the same
		boolean same = false;
		if (sz == tsz) {
			same = true;
			for (int i=0; i < sz; i++) {
				org.eclipse.epf.xml.uma.MethodElementProperty srcMep = 
					(org.eclipse.epf.xml.uma.MethodElementProperty) srcList.get(i);
				MethodElementProperty tgtMep = 
					(MethodElementProperty) tgtList.get(i);
				if (! srcMep.getName().equals(tgtMep.getName())) {
					same = false;
					break;
				}
				if (! srcMep.getValue().equals(tgtMep.getValue())) {
					same = false;
					break;
				}
			}
		}
		if (same) {
			return;
		}
		
		//Soruce and target are not the same
		tgtList.removeAll(tgtList);
		for (int i=0; i < sz; i++) {
			Object srcItem = srcList.get(i);
			if (srcItem instanceof org.eclipse.epf.xml.uma.MethodElementProperty) {
				org.eclipse.epf.xml.uma.MethodElementProperty mep = 
						(org.eclipse.epf.xml.uma.MethodElementProperty) srcItem;
				EClass objClass = FeatureManager.INSTANCE
				.getRmcEClass("MethodElementProperty");	//$NON-NLS-1$
				MethodElementProperty xmlMep = (MethodElementProperty) EcoreUtil.create(objClass);
				xmlMep.setValue(mep.getValue());
				xmlMep.setName(mep.getName());
				tgtList.add(xmlMep);
			}
		}
		setDirty(obj);
		//obj.eSet(feature, tgtList);
	}

	/**
	 * Sets reference value.
	 * @param obj
	 * @param featureName
	 * @param id
	 * @throws Exception
	 */
	public void setReferenceValue(EDataObject obj, String featureName, String id)
			throws Exception {
		if (obj == null || featureName == null || id == null) {
			return;
		}
		
		EObject value = getElement(id);
		if (value == null) {
			logger.logWarning(NLS.bind(ImportXMLResources.library_error_set_reference, featureName, id));

			return;
		}

		// find the feature and set the value
		EStructuralFeature feature = FeatureManager.INSTANCE.getRmcFeature(obj
				.eClass(), featureName);
		if (feature == null) {
			Object[] paras = new Object[] { getString(obj), featureName, id };
			logger.logWarning(NLS.bind(ImportXMLResources.library_error_set_reference_2, paras)); 
			return;
		}

		// don't iterate the containment feature
		if (value.eContainer() == obj) {
			return;
		}

		// String str = feature.getEType().getName();
		if (feature.isMany()) {
			try {
				List items = (List) obj.eGet(feature);
				if (!items.contains(value)) {
					items.add(value);
				}
			} catch (RuntimeException e) {
				Object[] paras = new Object[] { getString(obj), featureName, id };
				logger
						.logError(
								NLS.bind(ImportXMLResources.library_error_set_reference_2, paras), e); 
			}
		} else {
			obj.eSet(feature, value);
		}
		
		setDirty(obj);
	}

	/**
	 * Sets work order.
	 * @param umaWorkOrder
	 * @param predId
	 * @deprecated
	 */
	public void setWorkOrder(Object umaWorkOrder, String predId) {
		if (umaWorkOrder instanceof WorkOrder) {
			WorkBreakdownElement e = (WorkBreakdownElement) getElement(predId);
			((WorkOrder) umaWorkOrder).setPred(e);
			
			setDirty((EObject)umaWorkOrder);

		}
	}

	/**
	 * Fixes library.
	 */
	public void fixLibrary() {
		MethodLibrary rootObject = getRoot();
		for (Iterator it = ((MethodLibrary) rootObject).getMethodPlugins()
				.iterator(); it.hasNext();) {
			fixPlugin((MethodPlugin) it.next());
		}
	}
	
	/**
	 * fix task descriptors for import
	 * 
	 */
	public void fixTaskDescriptors(Map<String, TaskDescriptor> tdMap) {
		if (tdMap == null || tdMap.isEmpty()) {
			return;
		}		
		for (Iterator<Map.Entry<String, TaskDescriptor>> it = tdMap.entrySet().iterator(); it.hasNext();) {
			Map.Entry<String, TaskDescriptor> entry = it.next();
			String guid = entry.getKey();
			TaskDescriptor td = entry.getValue();
			org.eclipse.epf.uma.TaskDescriptor umaTd = (org.eclipse.epf.uma.TaskDescriptor) elementsMap.get(guid);
			assert(umaTd != null);
			if (umaTd == null) {
				continue;
			}
			List steps = td.getStep();
			for (int i=0; i<steps.size(); i++) {
				org.eclipse.epf.xml.uma.MethodElement step = (org.eclipse.epf.xml.uma.MethodElement) steps.get(i);
				Section umaStep =  (Section) elementsMap.get(step.getId());
				assert(umaStep != null);
				if (umaStep != null) {
					umaTd.getSelectedSteps().add(umaStep);
				}
			}			
		}		
	}

	private MethodPackage cpRoot = null;

	private MethodPackage dpRoot = null;

//	private MethodPackage pcRoot = null;

	private void fixPlugin(MethodPlugin plugin) {

		// fix the root custom categories
		fixCustomCategories(plugin);

		List cpPkgs = new ArrayList();
		List dpPkgs = new ArrayList();
//		List pcPkgs = new ArrayList();

		cpRoot = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.capabilityPatternPath);
		dpRoot = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.deliveryProcessPath);
//		pcRoot = UmaUtil.findMethodPackage(plugin,
//				ModelStructure.DEFAULT.processContributionPath);
		getAllPackages(cpRoot, cpPkgs);
		getAllPackages(dpRoot, dpPkgs);
		
//		if ( pcPkgs != null ) {
//			getAllPackages(pcRoot, pcPkgs);
//		}
			
		List procs = new ArrayList();
		for (Iterator it = plugin.eAllContents(); it.hasNext();) {
			EObject o = (EObject)it.next();
			boolean oldNotify = o.eDeliver();
			try	{
				// turn off notifications to avoid possible deadlock or thread issue
				// 154142 - import xml caused thread access error
				o.eSetDeliver(false);
				
				if (o instanceof ProcessComponent) {
					procs.add(o);
				} else if (o instanceof DescribableElement) {
/*					String pName = ((DescribableElement) o).getPresentationName();
					if (pName == null || pName.length() == 0) {
						((DescribableElement) o)
								.setPresentationName(((DescribableElement) o)
										.getName());
					}*/
				}
	
				// fix the name string
				if (o instanceof MethodElement && !(o instanceof Section)) {
					String name = ((MethodElement) o).getName();
					String new_name = StrUtil.makeValidFileName(name);
					if ( !new_name.equals(name) ) {
						((MethodElement) o).setName(new_name);
					}
				}
			} finally {
				o.eSetDeliver(oldNotify);
			}
		}

		if (procs.size() > 0) {
			for (Iterator it = procs.iterator(); it.hasNext();) {
				ProcessComponent pc = (ProcessComponent) it.next();
				Object proc = pc.getProcess();
				if (proc instanceof DeliveryProcess) {
					if (!dpPkgs.contains(pc)) {
						moveProcessComponent(pc, dpRoot);
					}
				} else if (proc instanceof CapabilityPattern) {
					if (!cpPkgs.contains(pc)) {
						moveProcessComponent(pc, cpRoot);
					}
				}
			}
		}
	}

	private void getAllPackages(MethodPackage pkg, List pkgs) {
		pkgs.add(pkg);
		for (Iterator it = pkg.getChildPackages().iterator(); it.hasNext();) {
			getAllPackages((MethodPackage) it.next(), pkgs);
		}
	}

	/**
	 * move the process package to the specified container, if the package is
	 * the only child of it's parent, move it's parent
	 * 
	 * @param pkg
	 * @param container
	 */
	private void moveProcessComponent(ProcessPackage pkg,
			MethodPackage container) {
		// make sure Capability patterns are in the Capability packages
		Object o = pkg.eContainer();
		if ((o instanceof ProcessPackage)
				&& (((ProcessPackage) o).getChildPackages().size() == 1)
				&& o != cpRoot && o != dpRoot ) {
			moveProcessComponent((ProcessPackage) o, container);
		} else {
			container.getChildPackages().add(pkg);
		}
	}

	/**
	 * find the root custom cagegory and put to the root package
	 * 
	 * @param plugin
	 *            MethodPlugin
	 */
	private void fixCustomCategories(MethodPlugin plugin) {
		ContentPackage pkg = UmaUtil.findContentPackage(plugin,
				ModelStructure.DEFAULT.customCategoryPath);
		List items = new ArrayList(pkg.getContentElements());

		List rootItems = new ArrayList();
		while (items.size() > 0) {
			CustomCategory cc = (CustomCategory) items.remove(0);
			rootItems.add(cc);
			
			// 158691Custom Category is different in exported library
			// need to remove sub-categories recursively
			fixCustomCategories(cc, items, rootItems);
		}

		TngUtil.getRootCustomCategory(plugin).getCategorizedElements().addAll(
				rootItems);

	}
	
	/**
	 * find the root custom categories by removing the sub-categories recursively
	 * 
	 * @param cc
	 * @param items
	 * @param rootItems
	 */
	private void fixCustomCategories(CustomCategory cc, List items, List rootItems) {
		for (Iterator it = cc.getSubCategories().iterator(); it.hasNext();) {
			Object item = it.next();
			items.remove(item);
			rootItems.remove(item);
			fixCustomCategories((CustomCategory)item, items, rootItems);
		}
		
		// also iterate the contained elements
		for (Iterator it = cc.getCategorizedElements().iterator(); it
				.hasNext();) {
			Object item = it.next();
			if (item instanceof CustomCategory) {
				items.remove(item);
				rootItems.remove(item);
				fixCustomCategories((CustomCategory)item, items, rootItems);
			}
		}
	}
	
	/**
	 * delete the un-needed elements are clear resources 
	 */
	public void deleteElements() {
		
		IFileManager fileMgr = Services.getFileManager();

		List deletedElements = new ArrayList();
		
		for (Iterator it = elementsMap.entrySet().iterator(); it.hasNext(); ) {
			Map.Entry entry = (Map.Entry)it.next();
			String id = (String)entry.getKey();
			MethodElement e = (MethodElement)entry.getValue();
			if ( sourceElementIDs.contains(id) ) {
				continue;
			} else if (overwrite) {
				boolean toDelete = !(e instanceof MethodLibrary || e instanceof MethodPlugin
									|| e instanceof MethodConfiguration);
				if (toDelete) {
					MethodElement plugin = UmaUtil.getMethodPlugin(e);
					toDelete = plugin != null && !isNewElement(plugin.getGuid())
					&& sourceElementIDs.contains(plugin.getGuid());
				}
				if (toDelete) {
					deletedElements.add(e);
					handleActivityRemoval(e);
					//EcoreUtil.remove(e);
					continue;
				}
			}
			
			if (!overwrite && mergeLevel == 2) {
				continue;
			}			
			
			if ( (e instanceof CustomCategory) && TngUtil.isRootCustomCategory( (CustomCategory)e ) ) {
				continue;
			}			
			
			// delete the element if the containg package is in the source library
			// don't delete if the package is not in the xml library
			MethodPackage pkg = TngUtil.getMethodPackage(e);
			
			if ( pkg != null ) { 
				String pid = pkg.getGuid();
				if ( sourceElementIDs.contains(pid) ) {
					deletedElements.add(e);
					handleActivityRemoval(e);
					
					// delete the element from the library
					//EcoreUtil.remove(e);				
				} else if (e instanceof Activity) {
					
					boolean toCheck = true;
					MethodPackage pc = pkg;					
					while(pc != null && ! (pc instanceof ProcessComponent)) {
						pc = TngUtil.getParentMethodPackage(pc);
					}
					if (pc instanceof ProcessComponent) {
						toCheck = sourceElementIDs.contains(pc.getGuid());
					}
					
					if (toCheck) {
						pkg = TngUtil.getMethodPackage(pkg);
						while (pkg != null) {
							pid = pkg.getGuid();
							if (sourceElementIDs.contains(pid)) {
								deletedElements.add(e);
								handleActivityRemoval(e);
								break;
							}
							pkg = TngUtil.getParentMethodPackage(pkg);
						}
					}
				}
			}
		}
		
		// delete the resources
		deleteResoruces(deletedElements);
	}

	//	164581
	private void handleActivityRemoval(MethodElement e) {
		if (!(e instanceof BreakdownElement)) {
			return;
		}
		BreakdownElement eact = (BreakdownElement) e;
		Activity sact = eact.getSuperActivities();
		if (sact != null) {
			sact.getBreakdownElements().remove(eact);
		}
	}
	
	// clear resources for deleted elements
	private void deleteResoruces(List deletedElements) {
		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 ||
					overwrite && e instanceof ProcessComponent) {
				obj = e;
			}
			if ( obj != null ) {
				MethodElement plugin = UmaUtil.getMethodPlugin(e);
				Resource pluginRes = plugin == null ? null : plugin.eResource();
				
				Resource res = obj.eResource();
				if ( res != null && res != pluginRes) {		//Protected from bugs like 177042
					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$
						}
					}
					
					EObject resMgr = MultiFileSaveUtil.getResourceManager(res);
					if (resMgr != null) {
						EcoreUtil.remove(resMgr);
					}
					EObject resDes = MultiFileSaveUtil.getResourceDescriptor(res);
					if (resDes != null) {
						EcoreUtil.remove(resDes);
					}
					if (overwrite) {						
						File folder = new File(file).getParentFile();
						File files[] = folder.listFiles();
						if (files == null || files.length == 0 ) {
							if ( debug ) {
								System.out.println("deleting folder resource: " + folder); //$NON-NLS-1$
							}
							if ( !fileMgr.delete(folder.getAbsolutePath()) ) {
								if ( debug ) {
									System.out.println("unable to delete folder file: " + folder); //$NON-NLS-1$
								}
							}
						}
					}
				}								
			}
			
			EcoreUtil.remove(e);
		}
	}
			
	/**
	 * @param guid
	 * @return true if the element given by guid is new.
	 */
	public boolean isNewElement(String guid) {
		return newElementsMap.containsKey(guid);
	}
	
	public void setMergeLevel(int mergeLevel) {
		this.mergeLevel = mergeLevel;
	}
	
	private boolean toHandle(EDataObject rmcObj, EStructuralFeature rmcFeature) {
		EStructuralFeature feature = rmcFeature;
		if (feature == null || feature.isDerived()) {
			return false;
		}
		
		EReference eref = null;
		if (rmcFeature instanceof EReference) {
			eref = (EReference) rmcFeature;
			if (eref.isContainment()) {
				if (mergeLevel != 2) {	//The old delete code would take of it
					return false;
				}
				if (eref.isMany()) {
					return false;
				}
			} else if (rmcObj instanceof ContentCategory) {
				if (mergeLevel == 2 && eref.isMany()) {
					return false;
				}
			} else if (rmcFeature == UmaPackage.eINSTANCE
					.getWorkBreakdownElement_LinkToPredecessor()) {
				return false;
			}
		}
		
		if (rmcObj instanceof MethodPlugin) {
			if (feature == UmaPackage.eINSTANCE.getMethodPlugin_MethodPackages()) {
				return false;
			}
		} else if (rmcObj instanceof MethodConfiguration) {
			if (eref != null) {
				return false;
			}
		} else if (rmcObj instanceof MethodPackage) {
			if (rmcFeature == UmaPackage.eINSTANCE.getMethodPackage_ChildPackages() &&
					!(rmcObj instanceof ProcessPackage)) {
				return false;
			}
		} 
		
		return true;
	}
	
	private boolean isManyReference(EStructuralFeature rmcFeature) {
		if (! (rmcFeature instanceof EReference)) {
			return false;
		}		
		return ((EReference) rmcFeature).isMany();
	}
	
	public void handleNullXmlValue(EDataObject xmlObj, EDataObject rmcObj, String xmlFeatureName) throws Exception {		
		if (rmcObj instanceof MethodLibrary) {
			return;
		}
		
		EStructuralFeature feature = FeatureManager.INSTANCE.getRmcFeature(
				rmcObj.eClass(), xmlFeatureName);
		if (! toHandle(rmcObj, feature)) {
			return;
		}

		Object rmcValue = rmcObj.eGet(feature);
		if (rmcValue == null) {
			return;
		}

		if (rmcValue instanceof List) {
			initRmcList(rmcObj, feature);
			return;
		}

		boolean oldNotify = rmcObj.eDeliver();
		rmcObj.eSet(feature, null);
		rmcObj.eSetDeliver(oldNotify);
		setDirty(rmcObj);
	}
	
	public void initListValueMerge(EDataObject xmlObj, EDataObject rmcObj, String xmlFeatureName,
			List xmlList, Set<EStructuralFeature> seenRmcFeatures) throws Exception {
		if (rmcObj instanceof MethodLibrary) {
			return;
		}
		
		if (! (xmlList instanceof List)) {
			return;
		}
		
		EStructuralFeature feature = FeatureManager.INSTANCE.getRmcFeature(
				rmcObj.eClass(), xmlFeatureName);
		if (feature == null || seenRmcFeatures.contains(feature)) {	//feature could be mapped from more than
			return;													//one xml features
		}
		seenRmcFeatures.add(feature);
		
		if (! toHandle(rmcObj, feature)) {
			return;
		}

		initRmcList(rmcObj, feature);
	}

	private void initRmcList(EDataObject rmcObj, EStructuralFeature feature) {
		if (!isManyReference(feature)) {
			return;
		}

		Object rmcValue = rmcObj.eGet(feature);
		if (!(rmcValue instanceof List)) {
			return;
		}
		List rmcList = (List) rmcValue;

		if (rmcList.isEmpty()) {
			return;
		}

		boolean oldNotify = rmcObj.eDeliver();
		rmcObj.eSetDeliver(false);
		rmcList.clear();
		rmcObj.eSetDeliver(oldNotify);
		setDirty(rmcObj);
	}
	
	public void handleWorkOrder(org.eclipse.epf.xml.uma.WorkOrder xmlWorkOrder, WorkOrder umaWorkOrder) {	
		org.eclipse.epf.xml.uma.WorkOrderType xmlLinkType = xmlWorkOrder.getLinkType();
		if (xmlLinkType != null) {
			WorkOrderType umaLinkType = org.eclipse.epf.uma.WorkOrderType
					.get(xmlLinkType.toString());
			umaWorkOrder.setLinkType(umaLinkType);
		}
						
		boolean isSuccessor = false;
		String xmlPropertiesValue = xmlWorkOrder.getProperties();
		String scopeValue = null;
		if (xmlPropertiesValue != null) {
			EClass objClass = FeatureManager.INSTANCE.getRmcEClass("MethodElementProperty");	//$NON-NLS-1$
			List tgtList = umaWorkOrder.getMethodElementProperty();
			tgtList.removeAll(tgtList);
			
			List<String> propList = TngUtil.convertStringsToList(xmlPropertiesValue, XMLLibrary.WorkOrderPropStringSep);
			for (String prop : propList) {
				if (! prop.startsWith("name=")) {		//$NON-NLS-1$
					continue;
				}
				int ix = prop.indexOf(XMLLibrary.WorkOrderPropStringFieldSep + "value=");//$NON-NLS-1$
				if (ix < 6) {
					continue;
				}
				String name = prop.substring(5, ix).trim();
				if (name.length() == 0) {
					continue;
				}
				int valueStartingIx = ix + 7;
				if (prop.length() < valueStartingIx) {
					continue;
				}
				String strFromValueStartingIx = prop.substring(valueStartingIx);
				String value = strFromValueStartingIx;
				ix = strFromValueStartingIx.indexOf(XMLLibrary.WorkOrderPropStringFieldSep + "scope=");//$NON-NLS-1$
				if (ix > 0) {
					value = strFromValueStartingIx.substring(0, ix);
					int scopeValueStartingIx = ix + 7;
					scopeValue = strFromValueStartingIx.substring(scopeValueStartingIx);
				}
			
				MethodElementProperty umaMep = (MethodElementProperty) EcoreUtil.create(objClass);
				umaMep.setName(name);
				umaMep.setValue(value);
				tgtList.add(umaMep);
				if (name.equals(MethodElementPropertyHelper.WORK_ORDER__SUCCESSOR)) {		//$NON-NLS-1$						 
					isSuccessor = true;
				}
			}
		}

		WorkBreakdownElement e = (WorkBreakdownElement) getElement(xmlWorkOrder.getValue());
		
		if (isSuccessor && scopeValue != null) {			
			EObject cont = e.eContainer();
			if (cont instanceof ProcessPackage) {
				ProcessPackage parent = (ProcessPackage) cont;
				ProcessElement scopeElement = (ProcessElement) getElement(scopeValue);
				if (scopeElement != null) {
					ProcessPackage scopePkg = (ProcessPackage) scopeElement.eContainer();
					parent.getProcessElements().remove(umaWorkOrder);
					scopePkg.getProcessElements().add(umaWorkOrder);
				}
			}
			e.getLinkToPredecessor().remove(umaWorkOrder);
		}
		
		umaWorkOrder.setPred(e);
		setDirty(umaWorkOrder);		
	}
	
}