//------------------------------------------------------------------------------
// 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.library.edit.util.MethodLibraryPropUtil;
import org.eclipse.epf.library.util.LibraryUtil;
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;
	
	private int synFreeLibIx = -1; //-1: unset, 0: false, 1: true;

	/**
	 * 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());
				if (xmlStep == null) {	//Bug 300749: this can happen if td's plugin is not in the exported list 
					xmlStep = buildSection(step);
				}
				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;
	}
	
	private org.eclipse.epf.xml.uma.Section buildSection(
			org.eclipse.epf.uma.MethodElement umaStep) {
		if (! (umaStep instanceof org.eclipse.epf.uma.Section)) {
			return null;
		}

		org.eclipse.epf.xml.uma.Section xmlSection = org.eclipse.epf.xml.uma.UmaFactory.eINSTANCE
				.createSection();
		
		List<EStructuralFeature> features = umaStep.eClass()
				.getEAllStructuralFeatures();
		
		for (EStructuralFeature feature : features) {
			Object value = umaStep.eGet(feature);
			try {
				if (value instanceof String) {	//Ignore other type values
					setAtributeFeatureValue(xmlSection, feature.getName(), value);
				}
			} catch (Exception e) {
				String msg = NLS.bind(
						ExportXMLResources.exportXMLService_feature_error,
						LibraryUtil.getTypeName(umaStep), feature.getName());
				logger.logError(msg, e);
			}
		}

		return xmlSection;
	}
	
	public boolean isSynFreeLib() {
		if (synFreeLibIx == -1) {
			synFreeLibIx = 0;
			
			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 false;
			}
			
			for (MethodElementProperty mep : mepList) {
				String name = mep.getName();
				if (name != null && name.equals(MethodLibraryPropUtil.Library_SynFree)) {
					String value = mep.getValue();
					synFreeLibIx = Boolean.parseBoolean(value) ? 1 : 0;
					break;
				}
			}
		}
		return synFreeLibIx > 0;
	}
	
}
