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

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EDataType;
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.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.sdo.EDataObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xml.type.XMLTypeFactory;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.eclipse.epf.common.serviceability.VersionUtil;
import org.eclipse.epf.dataexchange.util.ContentProcessor;
import org.eclipse.epf.dataexchange.util.ILogger;
import org.eclipse.epf.export.xml.ExportXMLResources;
import org.eclipse.epf.library.ILibraryManager;
import org.eclipse.epf.library.ILibraryResourceManager;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.xml.uma.BreakdownElement;
import org.eclipse.epf.xml.uma.ContentCategoryPackage;
import org.eclipse.epf.xml.uma.ContentPackage;
import org.eclipse.epf.xml.uma.DocumentRoot;
import org.eclipse.epf.xml.uma.MethodElement;
import org.eclipse.epf.xml.uma.MethodElementProperty;
import org.eclipse.epf.xml.uma.MethodLibrary;
import org.eclipse.epf.xml.uma.MethodPackage;
import org.eclipse.epf.xml.uma.MethodPlugin;
import org.eclipse.epf.xml.uma.ProcessComponent;
import org.eclipse.epf.xml.uma.ProcessPackage;
import org.eclipse.epf.xml.uma.Section;
import org.eclipse.epf.xml.uma.UmaFactory;
import org.eclipse.epf.xml.uma.UmaPackage;
import org.eclipse.epf.xml.uma.VariabilityType;
import org.eclipse.epf.xml.uma.WorkBreakdownElement;
import org.eclipse.epf.xml.uma.WorkOrder;
import org.eclipse.epf.xml.uma.WorkOrderType;
import org.eclipse.epf.xml.uma.util.UmaResourceFactoryImpl;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.text.SimpleDateFormat;
import commonj.sdo.Type;

/**
 * XmlLibrary represents a method library loaded from a specified xml file The
 * xml file should be valid to the xml schema for MethodLibrary
 * 
 * @author Jinhua Xi
 * @since 1.0
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=162153
 */
public class XMLLibrary {

	private String filePath;

	private ILogger logger;

	private ContentProcessor contentProc = null;

	private MethodLibrary rootObject;

	// map of content category package for each plugin id
	private Map contentCategoryPkgMap = new HashMap();

	// map of created elements, guid - EDataObject
	private Map elementsMap = new HashMap();
	
	private Map<String, String> guidToPlugNameMap;

	/**
	 * Creates a new instance.
	 */
	public XMLLibrary(ContentProcessor contentProc, ILogger logger,
			String filePath) {
		this.contentProc = contentProc;
		this.logger = logger;
		this.filePath = filePath;

	}

	/**
	 * @return root object.
	 */
	public EDataObject getRoot() {
		return this.rootObject;
	}

	/**
	 * @return file path string.
	 */
	public String getFilePath() {
		return this.filePath;
	}

	/**
	 * get an array of plugin ids in the library
	 * 
	 * @return
	 */
	public String[] getPluginIds() {
		List plugins = rootObject.getMethodPlugin();
		String[] ids = new String[plugins.size()];
		for (int i = 0; i < plugins.size(); i++) {
			ids[i] = ((MethodPlugin) plugins.get(i)).getId();
		}

		return ids;
	}

	/**
	 * @param id
	 * @param name
	 * @return a new XML library.
	 */
	public EDataObject createLibrary(String id, String name) {

		MethodLibrary root = UmaFactory.eINSTANCE.createMethodLibrary();
		String version = "";								//$NON-NLS-1$	
		for (Iterator iter = VersionUtil.getAllToolIDs().iterator();iter.hasNext();) {
			String toolID = (String)iter.next();
			String toolVersion = VersionUtil.getVersions(toolID).getMinToolVersionForCurrentXMLSchemaVersion().getToolVersion().toString();
			if (version.length() > 0) {
				version += VersionUtil.XML_VERSIONS_SEPARATOR;
			}
			version += toolID + VersionUtil.XML_TOOL_VERSION_SEPARATOR + toolVersion;		
		}
		if (version.length() > 0) {
			root.setTool(version);
		}
		return create(id, name, root);
	}

	/**
	 * Loads the xml file.
	 */
	public void load() throws Exception {
/*		try {*/
			ResourceSet resourceSet = new ResourceSetImpl();

			// Get the URI of the model file.
			//
			URI fileURI = URI.createFileURI((new File(this.filePath)).getAbsolutePath());

			// Create a resource for this file.
			//
			// Resource resource = resourceSet.createResource(fileURI);
			Resource resource = new UmaResourceFactoryImpl()
					.createResource(fileURI);
			resourceSet.getResources().add(resource);

			resource.load(new HashMap());

			// Resource resource = resourceSet.getResource(fileURI, false);

			// EClass eClass =
			// ExtendedMetaData.INSTANCE.getDocumentRoot(umaPackage);

			DocumentRoot root = (DocumentRoot) resource.getContents().get(0);
			for (Iterator itr = root.eContents().iterator(); itr.hasNext();) {
				Object o = itr.next();
				if (o instanceof MethodLibrary) {
					this.rootObject = (MethodLibrary) o;
					break;
				}
			}
/*
			// System.out.println("Resource loaded");
		} catch (IOException e) {
			logger.logError(NLS.bind(
					ExportXMLResources.xmlLibrary_error_load_xml, filePath), e);
		}*/
	}

	/**
	 * create the library and return the root object
	 * 
	 * @param filePath
	 * @return
	 */
	private MethodLibrary create(String id, String name, MethodElement root) {

		// Create a resource set
		//
		ResourceSet resourceSet = new ResourceSetImpl();

		// Get the URI of the model file.
		//
		File file = new File(this.filePath);
		URI fileURI = URI.createFileURI(file.getAbsolutePath());

		// Create a resource for this file.
		//
		// Resource resource = resourceSet.createResource(fileURI);
		Resource resource = new UmaResourceFactoryImpl()
				.createResource(fileURI);
		resourceSet.getResources().add(resource);

		// Add the initial model object to the contents.
		// root.setId(id);
		// root.setName(name);

		setElement(id, root);

		// this.rootObject = root;
		if (root != null) {
			resource.getContents().add(root);
		}

		try {
			Map options = new HashMap();
			options.put(XMLResource.OPTION_ENCODING, "UTF-8"); //$NON-NLS-1$
			resource.save(options);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (root instanceof MethodLibrary) {
			this.rootObject = (MethodLibrary) root;
		}

		return this.rootObject;
	}

	/**
	 * @param pluginId
	 * @return a content catergory package in the plugin given by pluginId.
	 */
	public EDataObject getContentCategoryPackage(String pluginId) {

		ContentCategoryPackage pkg = (ContentCategoryPackage) contentCategoryPkgMap
				.get(pluginId);
		if (pkg != null) {
			return pkg;
		}

		MethodPlugin plugin = (MethodPlugin) getElement(pluginId);
		if (plugin == null) {
			logger.logWarning(NLS.bind(ExportXMLResources.xmlLibrary_no_plugin,
					pluginId));
			return null;
		}

		pkg = UmaFactory.eINSTANCE.createContentCategoryPackage();
		pkg.setName("ContentCategories"); //$NON-NLS-1$

		setElement(EcoreUtil.generateUUID(), pkg);

		plugin.getMethodPackage().add(pkg);

		contentCategoryPkgMap.put(pluginId, pkg);
		return pkg;
	}

	/**
	 * Saves the xml file.
	 */
	public void save() throws Exception {
		// Save the contents of the resource to the file system.
		//
		Map options = new HashMap();
		options.put(XMLResource.OPTION_ENCODING, "UTF-8"); //$NON-NLS-1$
		Resource resource = rootObject.eResource();
		resource.save(options);
	}

	/**
	 * @return the root object.
	 */
	public EDataObject open() {
		return rootObject;
	}

	/**
	 * @param guid
	 * @return the corresponding base library element.
	 */
	public EDataObject getElement(String guid) {
		return (EDataObject) elementsMap.get(guid);
	}

	/**
	 * @param obj
	 * @return the corresponding base library element.
	 */
	public EDataObject getElement(Object obj) {
		if (obj instanceof MethodElement) {
			return getElement(((MethodElement) obj).getId());
		}

		return null;
	}

	
	/**
	 * @param obj
	 * @return elmenent id string.
	 */
	public String getElementId(EDataObject obj) {

		if (obj instanceof MethodElement) {
			return ((MethodElement) obj).getId();
		} else if (obj instanceof WorkOrder) {
			return ((WorkOrder) obj).getId();
		}

		return null;
	}

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

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

			elementsMap.put(guid, obj);
		}
	}

	// private void addElementToContainer(EDataObject container, EDataObject
	// child) {
	//		
	// try {
	// if ( container == null ) {
	// return;
	// }
	//			
	// if ( child instanceof MethodLibrary || child instanceof MethodPlugin ||
	// child instanceof MethodPackage ) {
	// return;
	// }
	//			
	// while ( !(container instanceof MethodPackage) && (container != null) ) {
	// container = container.eContainer();
	// }
	//			
	// if ( container instanceof ContentPackage ) {
	// ((ContentPackage)container).getContentElement().add(child);
	// } else if ( container instanceof ProcessPackage ) {
	// ((ProcessPackage)container).getProcessElement().add(child);
	// } else {
	// System.out.println("Don't know how to set element " + child);
	// }
	// } catch (RuntimeException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// }

	/**
	 * create a child element with the specified guid
	 * 
	 * @param container
	 *            container of the element to be created
	 * @param umaFeatureName
	 *            uma feature for the element to be created
	 * @param umaEClassName
	 *            uma EClass name for the feature
	 * @param umaElementType
	 *            uma element type for the element to be created
	 * @param guid
	 *            guid of the element to be created
	 * @return EDataObject the Xml uma element
	 */
	public EDataObject createElement(EDataObject container,
			String umaFeatureName, String umaEClassName, String umaElementType,
			String guid) {

		EDataObject obj = getElement(guid);
		if (obj == null) {
			if (FeatureManager.INSTANCE.isUnneededRmcFeature(umaFeatureName)) {
				return null;
			}
			EStructuralFeature feature = FeatureManager.INSTANCE.getXmlFeature(
					container.eClass(), umaFeatureName, umaElementType);
			if (feature == null) {
				logger.logWarning(NLS.bind(
						ExportXMLResources.xmlLibrary_no_feature, container
								.eClass().getName(), umaFeatureName));
				return null;
			}

			// if ( !(feature instanceof EReference) ) {
			// System.out.println("Error creating element: containment feature
			// should be EReference type. " + feature.getName());
			// //return null;
			// }

			// // 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();
			// if ( !c.getName().equals(umaEClassName) ) {
			// System.out.println("EClass name not match: " + c.getName() + "
			// --- " + umaEClassName);
			// }

			EClass objClass = FeatureManager.INSTANCE
					.getXmlEClass(umaEClassName);
			if (objClass == null) {
				logger.logWarning(NLS.bind(
						ExportXMLResources.xmlLibrary_no_class, umaEClassName));
				return null;
			}

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

			if (obj instanceof WorkOrder) {
				// WorkOrder is not contained in a processPackage in xml model
				// it's contained by the breakdownElement
				// so we save the element id-object to the map and continue
				// don't set the feature value
				
				// the workOrder in EPF UMA model is referenced by feature
				// WorkBreakDownElement_LinkToPredecessor,
				// the corresponding feature in the xml model is 
				// WorkBreakDownElement_Predecessor, 
				// the feature value is a list of guid of the WorkOrders
				// when this feature value is set in the setReferenceValue() call
				// get the XmlUma object, if it's WorkOrder, 
				// add to the current workorder to the WorkBreakDownElement
				// Jinhua Xi, 08/24/2006
				return obj;
			}

			// note: all element references are string type (id)
			// package references are object references
			if (feature.isMany()) {
				List values = (List) container.eGet(feature);
				try {
					if (feature instanceof EAttribute) {
						values.add(guid);

						// need to put the object in a container
						// for example, the ContaiedArtifacts
						addToContainer(container, obj);

					} else if (feature instanceof EReference) {
						try {
							values.add(obj);
						} catch (RuntimeException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					} else {
						logger
								.logWarning(NLS
										.bind(
												ExportXMLResources.xmlLibrary_error_create_element,
												feature.getName()));
					}
				} catch (RuntimeException e) {
					logger.logError(NLS.bind(
							ExportXMLResources.xmlLibrary_error_set_value, obj,
							container), e);
					// e.printStackTrace();
				}
			} else {
				if (feature instanceof EAttribute) {
					container.eSet(feature, guid);
					addToContainer(container, obj);
				} else if (feature instanceof EReference) {
					container.eSet(feature, obj);
				} else {
					logger.logWarning(NLS.bind(
							ExportXMLResources.xmlLibrary_error_create_element,
							feature.getName()));
				}
			}
		}

		return obj;
	}

	private void addToContainer(EObject container, EObject obj) {

		if (container == null) {
			return;
		}
		if (container instanceof ContentPackage) {
			((ContentPackage) container).getContentElement().add(obj);
		} else if (container instanceof ProcessPackage) {
			((ProcessPackage) container).getProcessElement().add(obj);
			// } else if ( (obj instanceof Constraint) && (container instanceof
			// MethodElement) ) {
			// // the owner rule should be a containment 0..n feature, waiting
			// for model fix
			// //((MethodElement)container).setO
		} else {
			addToContainer(container.eContainer(), obj);
		}
	}

	/**
	 * 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) {
			if (featureName.equals("methodElementProperty")) {		//$NON-NLS-1$
				setMepFeatureValue(obj, featureName, value);
				return;
			}
			logger.logWarning(NLS.bind(
					ExportXMLResources.xmlLibrary_invalid_feature_value,
					featureName, value));

			return;
		}

		// find the feature and set the value
		EStructuralFeature feature = FeatureManager.INSTANCE.getXmlFeature(obj
				.eClass(), featureName);
		if (feature == null) {

			// ignore missing features for WorkOrder
			if (!(obj instanceof WorkOrder)) {
				Object[] paras = new Object[] { featureName, obj, value };
				logger
						.logWarning(NLS
								.bind(
										ExportXMLResources.xmlLibrary_error_set_value_2,
										paras));
			}
			return;
		}

		// 158688 - Missing template files in exported xml library
		// process the attachment url
		if ( feature == UmaPackage.eINSTANCE.getGuidanceDescription_Attachment() ) {
			if ( value != null ) {
				value = contentProc.resolveAttachmentResources(obj, value.toString().trim());
			}
			obj.eSet(feature, value);
		}
		
		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 (value instanceof java.util.Date) {
					// convert java.util.Date to xml Date
					value = getXmlDate((java.util.Date) value);
				} else if ((contentProc != null)
						&& (obj instanceof MethodElement)
						&& (value instanceof String)) {
					value = contentProc.resolveResourceFiles(
							(MethodElement) obj, (String) value);
				} else if (value instanceof java.net.URI) {									
					org.eclipse.epf.uma.MethodPlugin srcPlugin = ExportResourceHandler.getSourcePlugin((org.eclipse.epf.xml.uma.MethodElement) obj);		
					value = srcPlugin.getName() + "/" + ((java.net.URI) value).getPath(); ////$NON-NLS-1$
					if (contentProc != null) {
						contentProc.copyResource((String) value, obj, srcPlugin);
					}
				}
				obj.eSet(feature, value);
			} catch (RuntimeException e) {
				Object[] paras = new Object[] { featureName, obj, value };
				logger
						.logError(
								NLS
										.bind(
												ExportXMLResources.xmlLibrary_error_set_value_2,
												paras), e);
			}
		} else {
			System.out.println(ExportXMLResources.xmlLibrary_error_set_value_3); 
		}

	}

	private void setMepFeatureValue(EDataObject obj, String featureName, Object value) {
		List srcList = (List) value;
		if (srcList == null || srcList.isEmpty()) {
			return;
		}
		EStructuralFeature feature = FeatureManager.INSTANCE.getXmlFeature(obj
				.eClass(), featureName);
		List tgtList = (List) obj.eGet(feature);
		for (int i=0; i < srcList.size(); i++) {
			Object srcItem = srcList.get(i);
			if (srcItem instanceof org.eclipse.epf.uma.MethodElementProperty) {
				org.eclipse.epf.uma.MethodElementProperty mep = 
						(org.eclipse.epf.uma.MethodElementProperty) srcItem;
				EClass objClass = FeatureManager.INSTANCE
				.getXmlEClass("MethodElementProperty");	//$NON-NLS-1$
				MethodElementProperty xmlMep = (MethodElementProperty) EcoreUtil.create(objClass);
				xmlMep.setValue(mep.getValue());
				xmlMep.setName(mep.getName());
				tgtList.add(xmlMep);
			}
		}
		//obj.eSet(feature, tgtList);
	}

	/**
	 * set the id references for the object
	 * 
	 * @param obj
	 *            EDataObject the object
	 * @param featureName
	 *            String the feature of the object
	 * @param idValue
	 *            String the id reference value of the feature
	 * @param valueType
	 *            Type the object type of the reference. Need to have this to
	 *            determine the xml feature in case the feature mappting is not
	 *            unique
	 * @throws Exception
	 */
	public void setReferenceValue(EDataObject obj, String featureName,
			String idValue, Type valueType) throws Exception {
		if (obj == null || featureName == null || idValue == null) {
			return;
		}

		if (FeatureManager.INSTANCE.isUnneededRmcFeature(featureName)) {
			return;
		}

		// find the feature and set the value
		EStructuralFeature feature = FeatureManager.INSTANCE.getXmlFeature(obj
				.eClass(), featureName, valueType.getName());
		if (feature == null) {
			Object[] paras = new Object[] { featureName, obj, idValue };
			logger.logWarning(NLS.bind(
					ExportXMLResources.xmlLibrary_error_set_reference, paras));
			return;
		}

		String str = feature.getEType().getName();
		if (str.equals("String")) { //$NON-NLS-1$
			if (feature.isMany()) {
				List l = (List) obj.eGet(feature);
				if (!l.contains(idValue)) {
					l.add(idValue);
				}
			} else {
				obj.eSet(feature, idValue);
			}
		} else if (feature == UmaPackage.eINSTANCE
				.getActivity_BreakdownElement()) {
			// special handling for breakdown element. In uma, breakdown
			// elements are under process packages
			// in xml model, they are owned by the activity
			EDataObject v = getElement(idValue);
			if (v instanceof BreakdownElement) {
				EObject old_container = v.eContainer();
				List l = (List) obj.eGet(feature);
				if (!l.contains(v)) {
					l.add(v);
				}

				// if the old container package is empty, delete it
				if ((old_container instanceof ProcessPackage)
						&& (old_container.eContainer() instanceof ProcessComponent)) {
					if (((ProcessPackage) old_container).getProcessElement()
							.size() == 0) {
						((ProcessPackage) old_container.eContainer())
								.getMethodPackage().remove(old_container);
					}
				}
			}
		} else if ( feature == UmaPackage.eINSTANCE.getWorkBreakdownElement_Predecessor() ) {
			// the orker order needs to be added to the WorkBreakdownElement
			// since in Xml model the work order is contained by the WorkBreakdownElement
			// Jinhua Xi, 08/24/2006
			Object v = getElement(idValue);
			if (v instanceof WorkOrder) {
				((WorkBreakdownElement)obj).getPredecessor().add(v);
			}
		} else {
			// not handled, add warning log
			// the id feature value is not set
			// JInhua Xi, TODO
		}
	}

	/**
	 * @param dt
	 * @return a Xml date.
	 */
	public Object getXmlDate(java.util.Date dt) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //$NON-NLS-1$
		String dtStr = sdf.format(dt);
		dtStr = dtStr.replace(' ', 'T');
		EDataType type = XMLTypePackage.eINSTANCE.getDateTime();
		return XMLTypeFactory.eINSTANCE.createFromString(type, dtStr);

	}

	private String getString(Object obj) {
		String str = ""; //$NON-NLS-1$
		if (obj instanceof MethodElement) {
			MethodElement me = (MethodElement) obj;
			str = me.getType().getName() + ":" + me.getName(); //$NON-NLS-1$
		} else if (obj != null) {
			str = obj.toString();
		}

		return str;
	}

	/**
	 * fix the library so that it meets the uma library standards
	 * 
	 */
	public void fixLibraryForImport() {

		fixGuid((MethodElement) rootObject);

		if (rootObject instanceof MethodLibrary) {
			for (Iterator it = ((MethodLibrary) rootObject).getMethodPlugin()
					.iterator(); it.hasNext();) {
				fixPlugin((MethodPlugin) it.next());
			}
		} else if (rootObject instanceof MethodPlugin) {
			fixPlugin((MethodPlugin) rootObject);
		}
	}

	/**
	 * fix the library so that it meets the xml schema standards
	 * also remove possible structure errors such as ProcessComponent without process in it.
	 * 
	 */
	public void fixLibraryForExport() {

		List invalidItems = new ArrayList();
		for (Iterator it = ((MethodLibrary) rootObject).eAllContents(); it.hasNext();) {
			Object obj = it.next();
			if ( obj instanceof ProcessComponent ) {
				org.eclipse.epf.xml.uma.Process proc = ((ProcessComponent)obj).getProcess();
				if ( proc == null ) {
					invalidItems.add(obj);
				}
			}
		}

		// remove the objects
		while (invalidItems.size() > 0 ) {
			EObject obj = (EObject)invalidItems.remove(0);
			EcoreUtil.remove(obj);
		}
	}
	
	/**
	 * fix task descriptors for export
	 * 
	 */
	public void fixTaskDescriptorsForExport(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.xml.uma.TaskDescriptor xmlTd = (org.eclipse.epf.xml.uma.TaskDescriptor) elementsMap.get(guid);
			assert(xmlTd != null);
			if (xmlTd == null) {
				continue;
			}
			List steps = td.getSelectedSteps();
			for (int i=0; i<steps.size(); i++) {
				org.eclipse.epf.uma.MethodElement step = (org.eclipse.epf.uma.MethodElement) steps.get(i);
				Section xmlStep =  (Section) elementsMap.get(step.getGuid());
				assert(xmlStep != null);
				if (xmlStep != null) {
					xmlStep = (Section) EcoreUtil.copy(xmlStep);
					xmlTd.getStep().add(xmlStep);
				}
			}			
		}		
	}
			
	/**
	 * get a list of referenced plugins for the library. The referenced plugins
	 * does not include the ones inside this library. When importing, these
	 * plugins must be in the target library already.
	 * 
	 * @return List a list of referenced plugins
	 */
	public List getReferencedPlugins() {

		List externalPlugins = new ArrayList();

		if (!(rootObject instanceof MethodLibrary)) {
			return externalPlugins;
		}

		List selectedPlugins = new ArrayList();
		for (Iterator it = ((MethodLibrary) rootObject).getMethodPlugin()
				.iterator(); it.hasNext();) {
			MethodPlugin plugin = (MethodPlugin) it.next();
			String id = plugin.getId();
			selectedPlugins.add(id);
			if (externalPlugins.contains(id)) {
				externalPlugins.remove(id);
			}

			for (Iterator itr = plugin.getReferencedMethodPlugin().iterator(); itr
					.hasNext();) {
				String ref = (String) itr.next();
				if (!selectedPlugins.contains(ref)
						&& !externalPlugins.contains(ref)) {
					externalPlugins.add(ref);
				}
			}
		}

		return externalPlugins;
	}

	private void fixGuid(MethodElement element) {
		if (element == null) {
			return;
		}

		// if the xml element does not have an id specified, create a new one
		String id = element.getId();
		if (id == null || id.equals("")) { //$NON-NLS-1$
			id = EcoreUtil.generateUUID();
			element.setId(id);
			String msg = NLS.bind(ExportXMLResources.xmlLibrary_new_id,
					getString(element), id);
			logger.logWarning(msg);
		} else {
			// check if the element has a unique id or not
			Object old = getElement(id);
			if ((old != null) && (old != element)) {
				if (! ( (old instanceof Section) && 
						(element instanceof Section) 
					   )) {
					logger.logWarning(NLS.bind(
						ExportXMLResources.xmlLibrary_id_not_unique, id));
				}
			}

			setElement(id, element);
		}
		// iterate the children
		for (Iterator it = element.eContents().iterator(); it.hasNext();) {
			Object o = it.next();
			if (o instanceof MethodElement) {
				fixGuid((MethodElement) o);
			}
		}
	}

	private void fixPlugin(MethodPlugin plugin) {

		// find all processes and make sure they are wrapped with a
		// ProcessComponent,
		// if not, create one.
		// collect the processes to be fixed,
		// don't fix within the iteration, may cause concurrent modification
		// exeception
		List procs = new ArrayList();
		for (Iterator it = plugin.eAllContents(); it.hasNext();) {
			EObject o = (EObject) it.next();
			if (isProcess(o)) {
				procs.add(o);
			}
		}

		if (procs.size() > 0) {
			for (Iterator it = procs.iterator(); it.hasNext();) {
				fixProcess((org.eclipse.epf.xml.uma.Process) it.next());
			}
		}
	}

	/**
	 * In EPF, a process (Capability pattern and Delivery Process) can be reside
	 * in a ProcessPackage or a ProcessComponent. If it's in a processComponent,
	 * it is treated as a root level process. If it's in a ProcessPackage, it is
	 * treated as a local copy of another process. So we need to check the
	 * parent and see it this process is contained by a ProcessComponent.
	 * 
	 * @param Obj
	 * @return boolean
	 */
	private boolean isProcess(EObject obj) {
		if (!(obj instanceof org.eclipse.epf.xml.uma.Process)) {
			return false;
		}

		obj = obj.eContainer();
		if (obj instanceof ProcessComponent) {
			return true;
		}

		// if it's immediate parent is not a ProcessComponent but it's within a
		// ProcessComponent
		// it's a local copy of the process
		while (((obj = obj.eContainer()) != null)
				&& (obj instanceof ProcessPackage)) {
			if (obj instanceof ProcessComponent) {
				return false;
			}
		}

		return true;
	}

	private void fixProcess(org.eclipse.epf.xml.uma.Process proc) {
		EDataObject container = (EDataObject) proc.eContainer();
		ProcessComponent pc = null;
		if (container instanceof ProcessComponent) {
			return;
		}

		if (!(container instanceof ProcessPackage)) {
			String msg = NLS
					.bind(
							ExportXMLResources.xmlLibrary_error_process_wrong_container,
							proc.getName(), container.getType().getName());
			logger.logWarning(msg);
			return;
		}

		pc = UmaFactory.eINSTANCE.createProcessComponent();
		String id = getTargetParentId(proc.getId());
		if (id == null) {
			id = EcoreUtil.generateUUID();
		}

		pc.setId(id);
		pc.setName(proc.getName());
		((ProcessPackage) container).getProcessElement().remove(proc);
		((ProcessPackage) container).getMethodPackage().add(pc);
		pc.setProcess(proc);

	}

	/**
	 * if the process exists in the target library, get the process component id
	 * from the target library
	 */
	private String getTargetParentId(String id) {
		ILibraryManager manager = LibraryService.getInstance()
				.getCurrentLibraryManager();
		if (manager != null) {
			EObject obj = manager.getMethodElement(id);
			if (obj != null) {
				obj = obj.eContainer();
				if (obj instanceof org.eclipse.epf.uma.MethodElement) {
					return ((org.eclipse.epf.uma.MethodElement) obj).getGuid();
				}
			}
		}

		return null;
	}

	/**
	 * @param pkg
	 * @return the list of all processes in pkg.
	 */
	public List getAllProcesses(MethodPackage pkg) {
		List processes = new ArrayList();
		_iteratePackageForProcesses(pkg, processes);

		return processes;
	}

	private void _iteratePackageForProcesses(MethodPackage pkg, List processes) {
		if (pkg instanceof ProcessComponent) {
			org.eclipse.epf.xml.uma.Process p = ((ProcessComponent) pkg)
					.getProcess();
			if (p != null && !processes.contains(p)) {
				processes.add(p);
			}
		}

		for (Iterator it = pkg.getMethodPackage().iterator(); it.hasNext();) {
			_iteratePackageForProcesses((MethodPackage) it.next(), processes);
		}
	}

	
	/**
	 * Save extra info (all plugin guids and names) in libTag's MethodElementProperty
	 */
	protected void storeExtraInfo(List<org.eclipse.epf.uma.MethodPlugin> plugins) {
		if (plugins == null) {
			return;
		}		
		
		EStructuralFeature feature = FeatureManager.INSTANCE.getXmlFeature(rootObject
				.eClass(), "methodElementProperty");		//$NON-NLS-1$
		
		List mepList = (List) rootObject.eGet(feature);
		EClass mepClass = FeatureManager.INSTANCE.getXmlEClass("MethodElementProperty");	//$NON-NLS-1$
		
		MethodElementProperty xmlMep = (MethodElementProperty) EcoreUtil.create(mepClass);
		
		//Version
		xmlMep.setValue("0");	//$NON-NLS-1$
		mepList.add(xmlMep);
					
		for (Iterator<org.eclipse.epf.uma.MethodPlugin> it = plugins.iterator(); it.hasNext();) {
			org.eclipse.epf.uma.MethodPlugin plug = it.next();
			
			xmlMep = (MethodElementProperty) EcoreUtil.create(mepClass);
			xmlMep.setValue(plug.getGuid());
			mepList.add(xmlMep);
			
			xmlMep = (MethodElementProperty) EcoreUtil.create(mepClass);
			xmlMep.setValue(plug.getName());
			mepList.add(xmlMep);
		}
		
	}
	
	/**
	 * Get guid to plugin map
	 */
	public Map<String, String> getGuidToPlugNameMap() {
		if (guidToPlugNameMap == null) {
			recallExtraInfo();
		}		
		return guidToPlugNameMap;
	}
	
	private void recallExtraInfo() {
		try {
			EStructuralFeature feature = FeatureManager.INSTANCE.getXmlFeature(rootObject
					.eClass(), "methodElementProperty");		//$NON-NLS-1$
			
			List<MethodElementProperty> mepList = (List<MethodElementProperty>) rootObject.eGet(feature);
			if (mepList == null || mepList.isEmpty()) {
				return;
			}
			guidToPlugNameMap = new HashMap<String, String>();
			
			MethodElementProperty mep = mepList.get(0);
			if (mep.getValue().equals("0")) { //$NON-NLS-1$  
				for (int i = 1; i < mepList.size();) {
					String guid = mepList.get(i).getValue();
					String name = mepList.get(i+1).getValue();
					guidToPlugNameMap.put(guid, name);
					i += 2;
				}
			}
		} catch (Exception e) {
			guidToPlugNameMap = new HashMap<String, String>();
			e.printStackTrace();
		}
	}
	
}
