//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.importing.xml.services;

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

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.sdo.EDataObject;
import org.eclipse.epf.common.service.versioning.VersionUtil;
import org.eclipse.epf.common.ui.util.MsgBox;
import org.eclipse.epf.common.ui.util.MsgDialog;
import org.eclipse.epf.dataexchange.util.ContentProcessor;
import org.eclipse.epf.dataexchange.util.IResourceHandler;
import org.eclipse.epf.export.services.DiagramHandler;
import org.eclipse.epf.export.xml.ExportXMLResources;
import org.eclipse.epf.export.xml.services.FeatureManager;
import org.eclipse.epf.export.xml.services.XMLLibrary;
import org.eclipse.epf.importing.ImportPlugin;
import org.eclipse.epf.importing.ImportResources;
import org.eclipse.epf.importing.services.ConfigurationImportService;
import org.eclipse.epf.importing.services.FileModifyChecker;
import org.eclipse.epf.importing.services.LibraryImportManager;
import org.eclipse.epf.importing.wizards.PluginModifyInfo;
import org.eclipse.epf.importing.wizards.SelectImportConfigurationSource;
import org.eclipse.epf.importing.xml.ImportXMLPlugin;
import org.eclipse.epf.importing.xml.ImportXMLResources;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.persistence.MultiFileResourceSetImpl;
import org.eclipse.epf.persistence.migration.IMigrator;
import org.eclipse.epf.persistence.migration.MappingUtil;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.services.IFileBasedLibraryPersister;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.xml.uma.Activity;
import org.eclipse.epf.xml.uma.CapabilityPattern;
import org.eclipse.epf.xml.uma.ContentCategory;
import org.eclipse.epf.xml.uma.ContentCategoryPackage;
import org.eclipse.epf.xml.uma.ContentPackage;
import org.eclipse.epf.xml.uma.DeliveryProcess;
import org.eclipse.epf.xml.uma.Discipline;
import org.eclipse.epf.xml.uma.Domain;
import org.eclipse.epf.xml.uma.Guidance;
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.TaskDescriptor;
import org.eclipse.epf.xml.uma.UmaPackage;
import org.eclipse.epf.xml.uma.WorkOrder;
import org.eclipse.epf.xml.uma.WorkOrderType;
import org.eclipse.osgi.util.NLS;

/**
 * Xml import service class to process the importing task
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public class ImportXMLService {

	private List unlockedPlugins; 
	
	private boolean error = false;
	
	private Map renameElementMap = new HashMap();
	
	private boolean overwrite = false;
	
	private int mergeLevel = 0;
	
	private IStatus fileCheckedOutStatus = null;
	
	private String xmlPath;

	private XMLLibrary xmlLib;

	private UmaLibrary umaLib;

	private ImportXMLogger logger = new ImportXMLogger();

	private List discardedElements = new ArrayList();

	private DiagramHandler diagramHandler;
	
	//tds with steps
	private Map<String, TaskDescriptor> tdMap;
	
	// map xml WorkOrder to uma WorkOrder
	Map workOrderMap = new HashMap();
	
	private IMigrator migrator;
	
	private boolean checkBasePlugins = true;

	/**
	 * The constructor
	 */
	public ImportXMLService() {

	}

	/**
	 * Loads the xml file.
	 * @param xmlPath
	 * @return true if succeeds.
	 */
	public boolean loadXml(final String xmlPath) {
		String versionError = versionCheck(xmlPath,	ImportXMLResources.importXMLWizard_title);		
		if (versionError != null) {
			return false;
		}
				
		this.xmlPath = xmlPath;

		logger.logMessage("Loading xml library ..."); //$NON-NLS-1$
		
		boolean ret = false;
		try {
			this.xmlLib = new XMLLibrary(null, logger, xmlPath);
			this.xmlLib.load();
			ret = checkOldPlugins();
		} catch (Exception e) {
			logger.logError(NLS.bind(
					ExportXMLResources.xmlLibrary_error_load_xml, xmlPath), e);
			final String errStr = e.toString();
			SafeUpdateController.syncExec(new Runnable() {	
				public void run() {	
					ImportXMLPlugin.getDefault().getMsgDialog().displayError(
						NLS.bind(ExportXMLResources.xmlLibrary_error_load_xml, xmlPath), errStr);
				}
			});
		}
		
		return ret;
	}
	
	private boolean checkOldPlugins() {
		
		unlockedPlugins = new ArrayList();
		List fileNameToCheck = new ArrayList();
		Map map = new HashMap();
		Map guidMap = new HashMap();
		List basePlugins = LibraryService.getInstance().getCurrentMethodLibrary()
											.getMethodPlugins();
		for (int i = 0; i < basePlugins.size(); i++) {
			org.eclipse.epf.uma.MethodPlugin plugin = (org.eclipse.epf.uma.MethodPlugin) basePlugins.get(i);
			map.put(plugin.getName(), plugin);
			guidMap.put(plugin.getGuid(), plugin);
		}
		
		List plugins = ((MethodLibrary) xmlLib.getRoot()).getMethodPlugin();
		List guids = new ArrayList();
		for (int i=0; i<plugins.size(); i++) {
			MethodElement elem = (MethodElement) plugins.get(i);
			guids.add(elem.getId());
			
			org.eclipse.epf.uma.MethodPlugin basePlugin = 
				(org.eclipse.epf.uma.MethodPlugin) map.get(elem.getName());
			boolean toAdd = false;
			if (basePlugin != null && ! basePlugin.getGuid().equals(elem.getId())
					&& ! basePlugin.getUserChangeable()) {
				toAdd = true;
			} else {
				basePlugin = 
					(org.eclipse.epf.uma.MethodPlugin) guidMap.get(elem.getId());
				if (basePlugin != null /*&& ! basePlugin.getName().equals(elem.getName())*/
						&& ! basePlugin.getUserChangeable()) {
					toAdd = true;
				} 
			}
			if (toAdd) {
				unlockedPlugins.add(basePlugin.getGuid());
				basePlugin.setUserChangeable(new Boolean(true));
				Resource res = basePlugin.eResource();
				if (res != null && res.getURI() != null) {
					String fileName = res.getURI().toFileString();
					fileNameToCheck.add(fileName);
				}
			}
		}
		if (fileNameToCheck.size() > 0) {
			final List modifiedFiles = fileNameToCheck;	
			SafeUpdateController.syncExec(new Runnable() {
				public void run() {
					fileCheckedOutStatus = FileModifyChecker.checkModify(modifiedFiles);
				}
			});
		}
		
		if (! unlockedPlugins.isEmpty() && (fileCheckedOutStatus != null)
				&& !fileCheckedOutStatus.isOK()) {
			// log error
			SafeUpdateController.syncExec(new Runnable() {
				public void run() {
					String title = ImportXMLResources.importXMLWizard_title; 
					String msg = ImportXMLResources.importXMLService_import_failed; 
					new MsgDialog(ImportPlugin.getDefault())
						.displayError(title, msg, fileCheckedOutStatus);
					}
			});
			return false;
		}
		
		final PluginModifyInfo modifyInfo = SelectImportConfigurationSource
										.checkModify(guids, MsgBox.getDefaultShell(), false);		

		// allow user to proceed with locked plugins
		if ( modifyInfo.lockedPlugins.size() > 0 ) {
			final boolean ret[] = new boolean[1];
			SafeUpdateController.syncExec(new Runnable() {
				public void run() {
					String WIZARD_TITLE = ImportXMLResources.importXMLWizard_title; 
					String message = modifyInfo.getLockedMessage().toString() +
						ImportResources.ImportPluginWizard_confirm_continue; 
					ret[0] = ImportXMLPlugin
							.getDefault().getMsgDialog().displayConfirmation(WIZARD_TITLE, message);
				}
			});		
			return ret[0];
		} 			
		return true;
	}
	
	/**
	 * @return the log file.
	 */
	public File getLogPath() {
		return logger.getLogPath();
	}

	/**
	 * Dispose
	 */
	public void dispose() {

		discardedElements.clear();
		workOrderMap.clear();
		logger.dispose();
	}

	/**
	 * Does XML export.
	 * @param monitor
	 * @throws Exception
	 */
	public void doImport(IProgressMonitor monitor) throws Exception {
		boolean refresh = RefreshJob.getInstance().isEnabled();
		try {
			if (refresh) {
				// disable resource refreshing during import
				//
				RefreshJob.getInstance().setEnabled(false);
			}
			
			handleTypeChanges();
			
			IResourceHandler handler = new ImportResourceHandler(new File(
					xmlPath).getParentFile(), new File(LibraryService
					.getInstance().getCurrentMethodLibraryLocation()));

			ContentProcessor contentProc = new ContentProcessor(handler,
					this.logger);
			
			diagramHandler = new DiagramHandler(new File(
					xmlPath).getParentFile(), new File(LibraryService
							.getInstance().getCurrentMethodLibraryLocation())) {				
				//[0]: sourceFile
				//[1]: targetFile
				protected File[] getFiles(org.eclipse.epf.uma.MethodElement elem) {
					File[] files = super.getFiles(elem, false);
										
					EDataObject xmlObj = xmlLib.getElement(elem.getGuid());
					if (xmlObj instanceof org.eclipse.epf.xml.uma.Process) {
						org.eclipse.epf.xml.uma.Process proc = 
								(org.eclipse.epf.xml.uma.Process) xmlObj;
						String uri = proc.getDiagramURI();
						if (uri != null && uri.length() > 0) {
							File file = new File(getSourceLibRoot(), uri);
							//System.out.println("LD: file: " + file);
							if (file.exists()) {
								files[0] = file;
								files[1] = new File(getTargetLibRoot(), uri);
							} else {
								//System.out.println("LD: files[0]: " + files[0]);
							}
						}					
					}
					
					return files;
				}
				
			};

			this.xmlLib.fixLibraryForImport();

			// make sure all the dependent plugins are there
			List referencedPlugins = xmlLib.getReferencedPlugins();
			if (referencedPlugins.size() > 0) {
				org.eclipse.epf.uma.MethodLibrary library = org.eclipse.epf.library.LibraryService
						.getInstance().getCurrentMethodLibrary();
				if (library != null) {
					List plugins = library.getMethodPlugins();
					for (Iterator it = plugins.iterator(); it.hasNext();) {
						String id = ((org.eclipse.epf.uma.MethodPlugin) it
								.next()).getGuid();
						referencedPlugins.remove(id);
					}
				}
			}

			if (isCheckBasePlugins() && referencedPlugins.size() > 0) {
				 Map<String, String> map = xmlLib.getGuidToPlugNameMap();
				for (Iterator it = referencedPlugins.iterator(); it.hasNext();) {
					String nameAndId = "";		//$NON-NLS-1$
					String id = (String) it.next();
					if (map != null) {
						String name = map.get(id);
						if (name != null) {
							nameAndId += name + ", ";//$NON-NLS-1$
						}
					}
					nameAndId += id;
					logger.logError(NLS.bind(ImportXMLResources.importXMLService_missing_plugin, nameAndId),
							null);			
				}

				throw new Exception(
						ImportXMLResources.importXMLService_error_missing_plugins);
			}

			this.umaLib = new UmaLibrary(renameElementMap, contentProc, logger, overwrite);
			this.umaLib.setMergeLevel(mergeLevel);

			EDataObject xmlRoot = this.xmlLib.getRoot();
			EDataObject umaRoot = this.umaLib.getRoot();
			
			logger.logMessage("create target library elements ..."); //$NON-NLS-1$
			creatEDataObjectTree(xmlRoot, umaRoot);

			logger
					.logMessage("copying all feature values for target library elements ..."); //$NON-NLS-1$
			iteratEDataObject((MethodElement) xmlRoot);

			logger.logMessage("fix the target library ..."); //$NON-NLS-1$
			umaLib.fixLibrary();
			umaLib.fixTaskDescriptors(tdMap);

			LibraryImportManager.handleNameReplace(renameElementMap);
			
			diagramHandler.postRegisterElements();
			
			// delete the un-needed elements
			logger.logMessage("delete unneeded elements ..."); //$NON-NLS-1$
			umaLib.deleteElements();
			
			final List modifiedFiles = FileModifyChecker.getModifiedFiles(LibraryService.getInstance().
										getCurrentMethodLibrary().eResource().getResourceSet());
			modifiedFiles.addAll(diagramHandler.getModifiedFiles());
			final IStatus fileCheckedOutStatus = FileModifyChecker.syncExecCheckModify(modifiedFiles);
			
			if (fileCheckedOutStatus.isOK()) {
			
				logger.logMessage("saving target library ..."); //$NON-NLS-1$
	
				List configs = LibraryService.getInstance()
				.getCurrentMethodLibrary().getPredefinedConfigurations();
				int configSz = configs == null ? 0 : configs.size();
				for (int i=0; i<configSz; i++) {
					org.eclipse.epf.uma.MethodConfiguration config = 
						(org.eclipse.epf.uma.MethodConfiguration ) configs.get(i);
					LibraryUtil.validateMethodConfiguration(null, config);
				}
				
				if (configSz != 0) {
					org.eclipse.epf.uma.MethodLibrary currLib = LibraryService.getInstance().getCurrentMethodLibrary();
					ILibraryPersister persister = ((MultiFileResourceSetImpl) currLib.eResource().getResourceSet()).getPersister();
					if (persister instanceof IFileBasedLibraryPersister) {
						IFileBasedLibraryPersister ip = (IFileBasedLibraryPersister) persister;
						File configFolder = ip.getDefaultMethodConfigurationFolder(currLib);
						if (configFolder != null) {
							ip.setDefaultMethodConfigurationFolder(currLib, configFolder);
						} else {
							throw new Exception(
									ImportXMLResources.importXMLService_import_failed);
						}
					}
				}
				
				// don't refresh the workspace
				if (unlockedPlugins != null && ! unlockedPlugins.isEmpty()) {
					LibraryImportManager.lockUnlockedPlugins(unlockedPlugins);
				}
				LibraryUtil.saveLibrary(LibraryService.getInstance()
						.getCurrentMethodLibrary(), false, false);
				diagramHandler.execute();				
	
				logger.logMessage("re-open target library ..."); //$NON-NLS-1$
				LibraryService.getInstance().reopenCurrentMethodLibrary();
				if (migrator != null) {
					org.eclipse.epf.uma.MethodLibrary lib = LibraryService.getInstance().getCurrentMethodLibrary();
					migrator.migrateXmlImportedLib(lib, monitor);					
					LibraryService.getInstance().reopenCurrentMethodLibrary();
				}
					
				logger.logMessage("import completed successfully ..."); //$NON-NLS-1$
			} else {
				SafeUpdateController.syncExec(new Runnable() {
					public void run() {
						String title = ImportXMLResources.importXMLWizard_title; 
						String msg = ImportXMLResources.importXMLService_import_failed; 
						new MsgDialog(ImportXMLPlugin.getDefault())
							.displayError(title, msg, fileCheckedOutStatus);
						}
				});
			}	
						
			//ResourceUtil.refreshResources(LibraryService.getInstance()
			//		.getCurrentMethodLibrary(), monitor);

		} catch (Exception e) {
			logger.logError(NLS.bind(ImportXMLResources.importXMLService_import_failed, e.getMessage()), e);

			throw e;

		} finally {
			if (refresh) {
				// re-enable resource refreshing
				//
				RefreshJob.getInstance().setEnabled(true);
			}
		}
	}

	private void creatEDataObjectTree(EDataObject xmlObj, EDataObject umaObj) {

		for (Iterator it = xmlObj.eContents().iterator(); it.hasNext();) {
			EDataObject child = (EDataObject) it.next();
			createRmcObject(child, umaObj);
		}
	}

	private void createRmcObject(EDataObject xmlElement,
			EDataObject targetContainer) {
		if (xmlElement instanceof MethodElementProperty) {
			return;
		}
		// get the targetContainer's containing feature
		EStructuralFeature feature = xmlElement.eContainmentFeature();
		createRmcObject(xmlElement, targetContainer, feature.getName());
	}

	private void createRmcObject(EDataObject xmlElement,
			EDataObject targetContainer, String containmentXmlFeature) {

		try {
			if (xmlElement == null) {
				return;
			}

			EDataObject umaElement = null;

			// don't create content category package since in uma, it's
			// seperated based on type
			if (xmlElement instanceof MethodPlugin) {
				MethodPlugin plugin = (MethodPlugin) xmlElement;
				umaElement = umaLib.createMethodPlugin(plugin.getId(), plugin
						.getName());
			} else if (xmlElement instanceof ContentCategoryPackage) {
				// don't create, do nothing
				// mark as discarded so we don't need to copy it's attributes
				setDiscarded(((ContentCategoryPackage) xmlElement).getId());

			} else if ((xmlElement instanceof ContentCategory)
					&& !(xmlElement.eContainer() instanceof Domain 
							|| xmlElement.eContainer() instanceof Discipline)
					|| (xmlElement.eContainer() instanceof ContentCategoryPackage)) {
				// create the content categories for root content categories,
				// not for sub-domain and sub-discipline
				// 154143 - import xml did not reserve the sub-discipline structure
				String pluginId = getPlugin(xmlElement).getId();
				umaElement = umaLib.createContentCategory(pluginId, xmlElement
						.eClass().getName(), xmlElement.getType().getName(),
						xmlLib.getElementId(xmlElement));
			} else {

				// if this is root level package, find the corresponding
				// container for the UMA object
				if (xmlElement instanceof MethodPackage
						&& xmlElement.eContainer() instanceof MethodPlugin) {
					if (xmlElement instanceof ContentPackage) {
						targetContainer = umaLib
								.getContentRootPackage(targetContainer);
					} else if (xmlElement instanceof ProcessComponent) {
						Object proc = ((ProcessComponent) xmlElement)
								.getProcess();
						if (proc instanceof CapabilityPattern) {
							targetContainer = umaLib
									.getCapabilityPatternRootPackage(targetContainer);
						} else if (proc instanceof DeliveryProcess) {
							targetContainer = umaLib
									.getDeliveryProcessRootPackage(targetContainer);
						}
					} else if (xmlElement instanceof ProcessPackage) {
						List procs = xmlLib
								.getAllProcesses((MethodPackage) xmlElement);
						if (procs != null && procs.size() > 0) {
							Object proc = procs.get(0);
							if (proc instanceof CapabilityPattern) {
								targetContainer = umaLib
										.getCapabilityPatternRootPackage(targetContainer);
							} else if (proc instanceof DeliveryProcess) {
								targetContainer = umaLib
										.getDeliveryProcessRootPackage(targetContainer);
							}
						}
					}
				}
				
				if (targetContainer instanceof org.eclipse.epf.uma.TaskDescriptor &&
					containmentXmlFeature.equals("step")) {	//$NON-NLS-1$
					return;
				}
				
				// get the containment feature so we can create the object of
				// the same type
				umaElement = umaLib.createElement(targetContainer,
						containmentXmlFeature, xmlElement.eClass().getName(),
						xmlElement.getType().getName(), xmlLib
								.getElementId(xmlElement));
				
				if (xmlElement instanceof TaskDescriptor) {
					TaskDescriptor td = (TaskDescriptor) xmlElement;
					if (td.getTask() != null) {
						List steps = td.getStep();
						if (steps != null && !steps.isEmpty()) {
							if (tdMap == null) {
								tdMap = new HashMap<String, TaskDescriptor>();
							}
							tdMap.put(td.getId(), td);
						}
					}
				}

				// xml WorkOrder does not have an id, need to map the uma Object
				if (xmlElement instanceof WorkOrder) {
					workOrderMap.put(xmlElement, umaElement);
				}
			}

			// recursive,
			// note, uma element might be null since we can't determine the
			// owner of the element yet
			creatEDataObjectTree(xmlElement, umaElement);

		} catch (Exception e) {
			// log the error and continue???
			e.printStackTrace();
		}
	}

	private MethodPlugin getPlugin(EObject element) {
		while ((element != null) && !(element instanceof MethodPlugin)) {
			element = element.eContainer();
		}

		return (MethodPlugin) element;
	}

	private EDataObject getRmcObject(MethodElement xmlObj) {
		if (xmlObj instanceof MethodLibrary) {
			return umaLib.getRoot();
		} else {
			String id = xmlObj.getId();
			return this.umaLib.getElement(id);
		}
	}

	private void iteratEDataObject(MethodElement srcObj) {
		iteratEDataObject_(srcObj);
		EDataObject targetObj = getRmcObject(srcObj);
		if (targetObj instanceof org.eclipse.epf.uma.MethodElement) {
			diagramHandler.registerElement((org.eclipse.epf.uma.MethodElement) targetObj); 
		}
	}
	
	private void iteratEDataObject_(MethodElement srcObj) {

		logger
				.logMessage(" === processing element " + srcObj.getType().getName() + ": " + srcObj.getName()); //$NON-NLS-1$ //$NON-NLS-2$

		if (isProcessed(srcObj.getId())) {
			return;
		}
		setProcessed(srcObj.getId());

		// if object is not created, it's xml wrapper package
		if (srcObj instanceof ContentCategoryPackage) {

			// iterate the child packages
			for (Iterator it = ((ContentCategoryPackage) srcObj)
					.getContentCategory().iterator(); it.hasNext();) {
				iteratEDataObject((MethodElement) it.next());
			}
			return;
		}

		EDataObject targetObj = getRmcObject(srcObj);
		EClass eClass = srcObj.eClass();

		EList features = eClass.getEAllStructuralFeatures();
		boolean isNewElement = umaLib.isNewElement(srcObj.getId()) || srcObj instanceof MethodLibrary;
		boolean isOldPlugin = !isNewElement && (srcObj instanceof MethodPlugin);
		
		Set<EStructuralFeature> seenRmcFeatures = new HashSet<EStructuralFeature>();
		for (Iterator it = features.iterator(); it.hasNext();) {
			EStructuralFeature feature = (EStructuralFeature) it.next();
						
			if (FeatureManager.INSTANCE.isUnneededXmlFeature(feature.getName())) {
				continue;
			}
			if (isOldPlugin && UmaPackage.eINSTANCE.getMethodPlugin_UserChangeable() == feature) {
				continue;
			}

			Object value = srcObj.eGet(feature);

			try {
				if (value == null) {
					umaLib.handleNullXmlValue(srcObj, targetObj, feature.getName());
					continue;
				}
				
				boolean isMep = feature.getName().equals("methodElementProperty"); //$NON-NLS-1$	
				if (value instanceof List && ! isMep) {
					umaLib.initListValueMerge(srcObj, targetObj, feature.getName(), 
							(List) value, seenRmcFeatures);
					
					for (Iterator itv = ((List) value).iterator(); itv
							.hasNext();) {
						Object src_value = itv.next();						

						if (src_value instanceof String) {

							// it's an id reference
							umaLib.setReferenceValue(targetObj, feature
									.getName(), (String) src_value);
						} else if (src_value instanceof MethodElement) {
							// set the reference
							MethodElement e = (MethodElement) src_value;
							String guid = e.getId();

							// don't set the containment feature value since
							// it's already handled
							// when creating the library structure
							if (!isDiscarded(guid) && e.eContainer() != srcObj) {
								umaLib.setReferenceValue(targetObj, feature
										.getName(), guid);
							}

							iteratEDataObject((MethodElement) src_value);
						} else if (src_value instanceof WorkOrder) {
							// WorkOrder is not method element and does not have
							// an id, need special handling
							// set the prede
							WorkOrder wr = (WorkOrder) src_value;
							Object umaWr = workOrderMap.get(wr);							
							//umaLib.setWorkOrder(umaWr, wr.getValue());
							if (umaWr instanceof org.eclipse.epf.uma.WorkOrder) {
								umaLib.handleWorkOrder(wr, (org.eclipse.epf.uma.WorkOrder) umaWr);
							}
						} else {
							logger
									.logMessage(NLS.bind(ImportXMLResources.importXMLService_element_not_handled, src_value));
						}
					}
				} else if (feature instanceof EReference && ! isMep) {

					// get the xml object and iterate again
					Object src_value = value;

					if (src_value instanceof WorkOrder) {
						logger.logMessage("workorder value"); //$NON-NLS-1$
					} else if (src_value instanceof String
							&& !isDiscarded((String) src_value)) {
						// it's an id reference
						umaLib.setReferenceValue(targetObj, feature.getName(),
								(String) src_value);
					} else if (src_value instanceof MethodElement) {
						// set the reference
						String guid = ((MethodElement) src_value).getId();
						if (guid == null) {
							logger
									.logWarning(NLS.bind(ImportXMLResources.importXMLService_element_without_id, ((MethodElement) src_value)
									.getName()));
						}
						if (!isDiscarded(guid)) {
							umaLib.setReferenceValue(targetObj, feature
									.getName(), guid);
						}
						iteratEDataObject((MethodElement) src_value);
					} else {
						logger
								.logWarning(NLS.bind(ImportXMLResources.importXMLService_element_not_handled, src_value));
					}

				} else {
					if (targetObj instanceof ContentCategoryPackage) {
						logger.logMessage("hrre"); //$NON-NLS-1$
					}

					if (value instanceof WorkOrderType) {
						value = ((WorkOrderType) value).getName();
					}
					
					boolean rename = false;
					if (!isNewElement && feature == org.eclipse.epf.xml.uma.UmaPackage.eINSTANCE.getNamedElement_Name()) {
						String oldName = (String)targetObj.eGet(org.eclipse.epf.uma.UmaPackage.eINSTANCE.getNamedElement_Name());
						String newName = (String)srcObj.eGet(feature);				
						if (!newName.equals(oldName)) {
							LibraryImportManager.ensureUniqueNameForExistingElement
								((org.eclipse.epf.uma.MethodElement) targetObj, oldName, newName, renameElementMap);
							rename = true;
						}
					}
					if (!rename) {
						umaLib.setAtributeFeatureValue(targetObj,
								feature.getName(), value);
					}
					if (isNewElement && feature == org.eclipse.epf.xml.uma.UmaPackage.eINSTANCE.getNamedElement_Name()) {
						org.eclipse.epf.uma.MethodElement elem = (org.eclipse.epf.uma.MethodElement) targetObj;
						EObject ceobj = elem.eContainer();						
						if (ceobj instanceof org.eclipse.epf.uma.MethodElement && 
								! umaLib.isNewElement(((org.eclipse.epf.uma.MethodElement) ceobj).getGuid())) {
							LibraryImportManager.ensureUniqueName(ceobj, elem, renameElementMap);
						}
					}

				}
			} catch (Exception e) {
				// log the error and continue???
				e.printStackTrace();
			}

		}

	}

	// goid of processed element
	private List processedElements = new ArrayList();

	private boolean isProcessed(String guid) {
		return processedElements.contains(guid);
	}

	private void setProcessed(String guid) {
		if (!processedElements.contains(guid)) {
			processedElements.add(guid);
		}
	}

	private boolean isDiscarded(String id) {
		return discardedElements.contains(id);
	}

	private void setDiscarded(String id) {
		discardedElements.add(id);
	}
	
	/**
	 * Sets overwrite attribute.
	 * @param b
	 */
	public void setOverwrite(boolean b) {
		overwrite = b;
	}	
	
	private String versionCheck(final String xmlPath, final String title) {
		final String[] ret = new String[1];
		ret[0] = null;
		SafeUpdateController.syncExec(new Runnable() {	
			public void run() {				
				VersionUtil.VersionCheckInfo info = VersionUtil.checkXMLVersion(new File(xmlPath));
				if (info == null) {
					ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldData_unknown, new Object[] {
							Platform.getProduct().getName()});					
				} else {
					if (info.result < 0) {
						try {
							migrator = MappingUtil.getMigratorByLibPath(xmlPath);
						} catch (Exception e) {
							ret[0] = e.toString();
						}
						if (migrator == null && ret[0] == null) {
							if (info.toolID.equals(VersionUtil.getPrimaryToolID())) {
								ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldData, new Object[] {
										info.toolVersion, Platform.getProduct().getName()});
							} else {
								ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldData_unknown, new Object[] {
										Platform.getProduct().getName()});					
							}
						}
					} else if (info.result > 0) {
						if (info.toolID.equals(VersionUtil.getPrimaryToolID())) {
							ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldTool, new Object[] {
								info.toolVersion, Platform.getProduct().getName()});
						} else {
							ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldTool_unknown, new Object[] {
									Platform.getProduct().getName()});
						}
					} 
				}
				if (ret[0] != null) {
					ImportXMLPlugin.getDefault().getMsgDialog().displayError(title, ret[0]);					
				}
			}
		});		
		return ret[0];
	}
	
	 public void handleTypeChanges() {
		org.eclipse.epf.uma.MethodLibrary baseLib = LibraryService.getInstance()
												.getCurrentMethodLibrary();
		HashMap baseMap = new HashMap();
		ConfigurationImportService.collectPotentialTypeChanged(baseLib, baseMap);
		
		HashMap eClassObjMap = new HashMap();
		HashMap importMap = new HashMap();
		for (Iterator it = xmlLib.getRoot().eAllContents(); it.hasNext();) {
			Object obj = it.next();
			if (obj instanceof Guidance ||
				obj instanceof Activity) {
				MethodElement xmlElement = (MethodElement) obj;
				String eClassName = xmlElement.eClass().getName();
				Object eClassObj = eClassObjMap.get(eClassName);
				if (eClassObj == null) {
					EClass objEClass = FeatureManager.INSTANCE.getRmcEClass(eClassName);
					if (objEClass != null) {
						eClassObj = UmaFactory.eINSTANCE.create(objEClass);
						eClassObjMap.put(eClassName, eClassObj);	
					}
				}
				if (eClassObj != null) {
					importMap.put(xmlElement.getId(), eClassObj);
				}
			}
		}
		
		ConfigurationImportService.handleTypeChanges(baseMap, importMap);	
	}
	 
	private boolean isCheckBasePlugins() {
		return checkBasePlugins;
	}

	public void setCheckBasePlugins(boolean checkBasePlugins) {
		this.checkBasePlugins = checkBasePlugins;
	}

	public void setMergeLevel(int mergeLevel) {
		this.mergeLevel = mergeLevel;
	}
	
}
