//------------------------------------------------------------------------------
// 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.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.service.versioning.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.LibraryService;
import org.eclipse.epf.library.edit.util.MethodElementPropertyHelper;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.ecore.IModelObject;
import org.eclipse.epf.uma.ecore.Type;
import org.eclipse.epf.xml.uma.BreakdownElement;
import org.eclipse.epf.xml.uma.ContentCategoryPackage;
import org.eclipse.epf.xml.uma.ContentElement;
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.ProcessElement;
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;

/**
 * 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 {

	public static final String WorkOrderPropStringSep = "\n\n";			//$NON-NLS-1$
	public static final String WorkOrderPropStringFieldSep = "\n";			//$NON-NLS-1$
	
	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;
	
	private Map<WorkOrder, org.eclipse.epf.uma.WorkOrder> successOrWorkOrderMap;

	/**
	 * 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 IModelObject 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 IModelObject 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 IModelObject 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 IModelObject open() {
		return rootObject;
	}

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

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

		return null;
	}

	
	/**
	 * @param obj
	 * @return elmenent id string.
	 */
	public String getElementId(IModelObject 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, IModelObject 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 IModelObject createElement(IModelObject container,
			String umaFeatureName, String umaEClassName, String umaElementType,
			String guid) {

		IModelObject 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 = (IModelObject) 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((ContentElement)obj);
		} else if (container instanceof ProcessPackage) {
			((ProcessPackage) container).getProcessElement().add((ProcessElement)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(IModelObject obj, String featureName,
			Object value) throws Exception {
		if (obj == null || featureName == null || value == null) {
			return;
		}

		if (value instanceof List || value instanceof IModelObject) {
			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(IModelObject obj, String featureName, Object value) {
		List srcList = (List) value;
		if (srcList == null || srcList.isEmpty()) {
			return;
		}
		if (obj instanceof WorkOrder) {
			setMepFeatureValueForWorkOrder(srcList, (WorkOrder) obj);
			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);
	}

	private void setMepFeatureValueForWorkOrder(List srcList, WorkOrder xmlWorkOrder) {
		Object obj = getSuccessOrWorkOrderMap().get(xmlWorkOrder);
		org.eclipse.epf.uma.WorkOrder umaWorkOrder = null;
		org.eclipse.epf.uma.ProcessElement scopeElement = null;
		if (obj instanceof org.eclipse.epf.uma.WorkOrder) {
			umaWorkOrder = (org.eclipse.epf.uma.WorkOrder) obj;
		}
		
		
		
		String propertiesValue = "";	//$NON-NLS-1$	
		for (Object srcItem : srcList) {
			if (srcItem instanceof org.eclipse.epf.uma.MethodElementProperty) {
				org.eclipse.epf.uma.MethodElementProperty mep = 
						(org.eclipse.epf.uma.MethodElementProperty) srcItem;
				String srcName = mep.getName();
				String srcValue = mep.getValue();
				if (srcName != null && srcValue != null
						&& srcName.length() > 0 && srcValue.length() > 0) {
					if (propertiesValue.length() > 0) {
						propertiesValue += WorkOrderPropStringSep;				//$NON-NLS-1$
					}
					propertiesValue += "name=" + srcName;		//$NON-NLS-1$
					propertiesValue += WorkOrderPropStringFieldSep + "value=" + srcValue;	//$NON-NLS-1$
					
					if (umaWorkOrder != null && srcName.equals(MethodElementPropertyHelper.WORK_ORDER__SUCCESSOR)) {
						if (scopeElement == null) {
							Object cont = umaWorkOrder.eContainer();
							if (cont instanceof org.eclipse.epf.uma.ProcessPackage) {
								List<org.eclipse.epf.uma.ProcessElement> peList = 
									((org.eclipse.epf.uma.ProcessPackage) cont).getProcessElements();
								if (peList != null) {
									for (org.eclipse.epf.uma.ProcessElement pe : peList) {
										if (pe instanceof org.eclipse.epf.uma.Activity) {
											scopeElement = pe;
											break;
										}
									}
								}
							}
						}
						if (scopeElement != null) {
							propertiesValue += WorkOrderPropStringFieldSep + "scope=" + scopeElement.getGuid();		//$NON-NLS-1$
						}
					}
					
				}
			}
		}
		if (propertiesValue.length() > 0) {
			xmlWorkOrder.setProperties(propertiesValue);
		}
	}

	/**
	 * 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(IModelObject 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
			IModelObject 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((WorkOrder)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) {
		IModelObject container = (IModelObject) 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();
		}
	}

	public Map<WorkOrder, org.eclipse.epf.uma.WorkOrder> getSuccessOrWorkOrderMap() {
		if (successOrWorkOrderMap == null) {
			successOrWorkOrderMap = new HashMap<WorkOrder, org.eclipse.epf.uma.WorkOrder>();
		}
		return successOrWorkOrderMap;
	}
	
}
