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

	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);
					//EcoreUtil.remove(e);
					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);
					
					// delete the element from the library
					//EcoreUtil.remove(e);				
				}
			}
		}
		
		// delete the resources
		deleteResoruces(deletedElements);
	}
	
	// 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 ) {
				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);
						}
					}
					
					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);
	}
}