//------------------------------------------------------------------------------
// 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 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.importing.xml.ImportXMLPlugin;
import org.eclipse.epf.importing.xml.ImportXMLResources;
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.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.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.ProcessComponent;
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 ILogger logger;

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

	// 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(ContentProcessor contentProc, ILogger logger, boolean overwrite) {
		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(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) {
			obj = LibraryService.INSTANCE.createPlugin(name, id);

			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(
					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(obj);
				} else if (obj instanceof ProcessComponent) {
					MethodPackage pkg_cp = UmaUtil.findMethodPackage(plugin,
							ModelStructure.DEFAULT.capabilityPatternPath);
					pkg_cp.getChildPackages().add(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(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(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 {
		if (obj == null || featureName == null || value == null) {
			return;
		}
		
		if (value instanceof List || value instanceof EDataObject) {
			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$
					value = new java.net.URI(value.toString());

					// need to copy the resource file to the target library
					contentProc.copyResource(((java.net.URI) value).getPath());
				} 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)); 
		}

	}

	/**
	 * 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
	 */
	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 ( (e instanceof CustomCategory) && TngUtil.isRootCustomCategory( (CustomCategory)e ) ) {
				continue;
			}
			handleActivityRemoval(e);	
			
			// 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);
					
					// delete the element from the library
					//EcoreUtil.remove(e);				
				}
			}
		}
		
		// delete the resources
		deleteResoruces(deletedElements);
	}

	//	164581
	private void handleActivityRemoval(MethodElement e) {
		if (!(e instanceof Activity)) {
			return;
		}
		Activity eact = (Activity) 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);
					}
					
					if ( !fileMgr.delete(file) ) {
						if ( debug ) {
							System.out.println("unable to delete file: " + file);
						}
					}
					
					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);
							}
							if ( !fileMgr.delete(folder.getAbsolutePath()) ) {
								if ( debug ) {
									System.out.println("unable to delete folder file: " + folder);
								}
							}
						}
					}
				}								
			}
			
			EcoreUtil.remove(e);
		}
	}
			
	/**
	 * @param guid
	 * @return true if the element given by guid is new.
	 */
	public boolean isNewElement(String guid) {
		return newElementsMap.containsKey(guid);
	}
}