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

import java.io.File;
import java.io.FileFilter;
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.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.epf.authoring.ui.views.LibraryView;
import org.eclipse.epf.common.serviceability.MsgDialog;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.XMLUtil;
import org.eclipse.epf.export.services.ConfigurationExportService;
import org.eclipse.epf.export.services.LibraryDocument;
import org.eclipse.epf.importing.ImportPlugin;
import org.eclipse.epf.importing.ImportResources;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.LibraryServiceUtil;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.library.util.ResourceUtil;
import org.eclipse.epf.persistence.MultiFileSaveUtil;
import org.eclipse.epf.persistence.migration.UpgradeCallerInfo;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.persistence.util.PersistenceUtil;
import org.eclipse.epf.resourcemanager.ResourceManager;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.osgi.util.NLS;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * Imports a method plug-in into the current library.
 * 
 * @author Jinhua Xi
 * @author Kelvin Low
 * @since 1.0
 */
public class PluginImportingService {

	private UpgradeCallerInfo upGradeInfo;
	
	//Temp flag indicating use of the new merge scheme
	private static boolean newMergeScheme = true; 
	
	private PluginImportData data;

	LibraryDocument importingLibDoc;
	LibraryDocument targetLibDoc;

	// Flag to indicate the file checkout status.
	IStatus fileCheckedOutStatus = null;

	/**
	 * Creates a new instance.
	 */
	public PluginImportingService(PluginImportData data) {
		this.data = data;
	}

	/**
	 * Validates the plug-in against the current library, collects all the
	 * informations including plug-in info, configuation info and error info.
	 * Call this method, then call getError(), getPlugins(), getConfigs().
	 */
	public void validate(IProgressMonitor monitor) {
		try {
			if (monitor != null) {
				monitor.setTaskName(ImportResources.PluginImportingService_MSG0); //$NON-NLS-1$
			}

			if (this.data == null) {
				return;
			}

			this.data.clear();

			// Prepare the lib files.
			File importingLibPath = new File(data.llData.getParentFolder()
					+ File.separator + LibraryDocument.exportFile);
			if (!importingLibPath.exists()) {
				data
						.getErrorInfo()
						.addError(
								NLS.bind(ImportResources.PluginImportingService_MSG1, importingLibPath.toString())); 
				return;
			}
			
			boolean handleVersion = true;
			if (handleVersion) {
				upGradeInfo = new ConfigurationImportService.UpgradeInfo(UpgradeCallerInfo.upgradeImportPlugin, importingLibPath);
				if (! ConfigurationImportService.handleToolVersion(importingLibPath, upGradeInfo)) {
					data
					.getErrorInfo()
					.addError(
							NLS.bind(ImportResources.importPluginsWizard_ERR_Import_plugin, importingLibPath.toString())); 
					return;
				}
				if (upGradeInfo.getCopiedLibFile() != null) {
					importingLibPath = upGradeInfo.getCopiedLibFile();
				}
			} else {
				String versionError = ConfigurationImportService.versionCheck(importingLibPath.getAbsolutePath(), 
						ImportResources.importPluginsWizard_title);
				if (versionError != null) {
					data.getErrorInfo().addError(versionError);
					return;
				}
			}

			importingLibDoc = new LibraryDocument(importingLibPath);
			
			File libFile = new File(LibraryService.getInstance()
					.getCurrentMethodLibrary().eResource().getURI()
					.toFileString());
			targetLibDoc = new LibraryDocument(libFile);

			scanLibraryFile(importingLibDoc);
		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}

	/**
	 * Performs import.
	 */
	public void performImport(IProgressMonitor monitor) throws Exception {

		// need to disable the workspace refreshing
		boolean refresh = RefreshJob.getInstance().isEnabled();
		try {
			if (refresh) {
				// disable resource refreshing during import
				//
				RefreshJob.getInstance().setEnabled(false);
			}

			__doImport(monitor);

		} finally {
			if (refresh) {
				// re-enable resource refreshing
				//
				RefreshJob.getInstance().setEnabled(true);
			}
			if (upGradeInfo != null) {
				upGradeInfo.removeCopiedLibrary();
				upGradeInfo = null;
			}
		}
	}

	private void __doImport(IProgressMonitor monitor) {
		try {
			if (monitor != null) {
				monitor.setTaskName(ImportResources.PluginImportingService_MSG3); //$NON-NLS-1$
			}

			List unlockedPlugins = unlockPlugins();

			// To import the plug-ins, we need to do the following:
			// 1. Delete the plug-ins in the current library if user specify
			// remove
			// 2. Copy the selected plugin files to the destination
			// 3. Update the library.xmi
			// 4. Reload the library
			
			File libFile = targetLibDoc.getFile();
			
			if (newMergeScheme) {			
				merge(targetLibDoc);
				if (unlockedPlugins.size() > 0) {
					lockUnlockedPlugins(unlockedPlugins);
					LibraryService.getInstance().saveCurrentMethodLibrary();
					LibraryService.getInstance().reopenCurrentMethodLibrary();
				}
				MethodLibrary lib = LibraryService.getInstance().getCurrentMethodLibrary();
				ResourceUtil.refreshResources(lib, monitor);
				return;
			}			

			// // Remove existing entries.
			// removeExistingEntries(targetLibDoc);

			// Import entries and copy files.
			if (importEntries(targetLibDoc)) {
				// Save the updated library file.
				targetLibDoc.save();

				// Replace the guid of the old MethodLibrary with the new one.
				fixLibraryGuid(libFile.getParentFile(), importingLibDoc
						.getLibraryGuid(), targetLibDoc.getLibraryGuid());

				// Reopen the library.
				LibraryService.getInstance().reopenCurrentMethodLibrary();

				// Finally, re-lock the unlocked plugins and save the library
				// again.
				if (unlockedPlugins.size() > 0) {
					lockUnlockedPlugins(unlockedPlugins);
					LibraryService.getInstance().saveCurrentMethodLibrary();
				}
			}

			// Re-open library and fresh the workspace.
			LibraryService.getInstance().reopenCurrentMethodLibrary();

			// refresh library files in workspace
			//
			MethodLibrary lib = LibraryService.getInstance().getCurrentMethodLibrary();
			ResourceUtil.refreshResources(lib, monitor);

		} catch (Exception e) {
			ImportPlugin.getDefault().getLogger().logError(e);
		}
	}

	private List unlockPlugins() {

		List pluginIds = new ArrayList();

		PluginImportData.PluginInfo info;
		for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
			info = (PluginImportData.PluginInfo) it.next();
			if ((info.existingPlugin != null) && info.selected) {
				if (info.existingPlugin.getUserChangeable().booleanValue() == false) {
					info.existingPlugin.setUserChangeable(new Boolean(true));
					pluginIds.add(info.existingPlugin.getGuid());
				}
			}
		}

		return pluginIds;
	}

	private void lockUnlockedPlugins(List unlockedPlugins) {
		List plugins = LibraryService.getInstance().getCurrentMethodLibrary()
				.getMethodPlugins();
		for (Iterator it = plugins.iterator(); it.hasNext();) {
			MethodPlugin plugin = (MethodPlugin) it.next();
			if (unlockedPlugins.contains(plugin.getGuid())) {
				plugin.setUserChangeable(new Boolean(false));
			}
		}
	}

	private boolean importEntries(LibraryDocument targetLibDoc) {
		// 1. Find the entries to be removed.
		List importList = new ArrayList();
		List newList = new ArrayList();
		PluginImportData.PluginInfo info;
		for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
			info = (PluginImportData.PluginInfo) it.next();
			if (info.selected) {
				if (info.existingPlugin == null) {
					newList.add(info.guid);
				}

				importList.add(info.guid);
			}
		}

		PluginImportData.ConfiguarationInfo cinfo;
		for (Iterator it = data.getConfigs().iterator(); it.hasNext();) {
			cinfo = (PluginImportData.ConfiguarationInfo) it.next();
			if (cinfo.selected) {
				if (cinfo.existingConfig == null) {
					newList.add(cinfo.guid);
				}

				importList.add(cinfo.guid);

			}
		}

		// 2. Iterate the docuemnt and add the new entries.
		if (!newMergeScheme) {
			importLibEntries(targetLibDoc, newList);
		} else {
			MethodLibrary lib = LibraryService.getInstance().getCurrentMethodLibrary();
			ensureUniqueNames(lib.getMethodPlugins());
			ensureUniqueNames(lib.getPredefinedConfigurations());
		}
		return copyFiles(targetLibDoc, importList, newList);
	}

	private void importLibEntries(LibraryDocument targetLibDoc, List newList) {

		if (newList == null || newList.size() == 0) {
			return;
		}

		// Add plug-ins.
		NodeList nodes = importingLibDoc.getPlugins();
		for (int i = 0; i < nodes.getLength(); i++) {
			Element node = (Element) nodes.item(i);
			String guid = LibraryDocument.getGuid(node);
			if (newList.contains(guid)) {
				targetLibDoc.addPlugin(node);
			}
		}

		// Add configurations.
		nodes = importingLibDoc.getConfigurations();
		for (int i = 0; i < nodes.getLength(); i++) {
			Element node = (Element) nodes.item(i);
			String guid = LibraryDocument.getGuid(node);
			if (newList.contains(guid)) {
				targetLibDoc.addConfiguration(node);
			}
		}

		// add resource entries
		nodes = importingLibDoc.getResourceDescriptors();
		for (int i = 0; i < nodes.getLength(); i++) {
			Element node = (Element) nodes.item(i);
			String guid = node.getAttribute(LibraryDocument.ATTR_id);
			if (newList.contains(guid)) {
				targetLibDoc.addResource(node);
			}
		}

		// Add the resource sub managers.
		nodes = importingLibDoc.getResourceSubManagers();
		for (int i = 0; i < nodes.getLength(); i++) {
			Element node = (Element) nodes.item(i);
			String guid = LibraryDocument.getSubManagerBaseGuid(node
					.getAttribute(LibraryDocument.ATTR_href));
			if (newList.contains(guid)) {
				targetLibDoc.addResource(node);
			}
		}

	}

	private boolean copyFiles(LibraryDocument targetLibDoc, List importList,
			List newList) {

		for (Iterator it = importList.iterator(); it.hasNext();) {
			String guid = (String) it.next();
			String src_uri = importingLibDoc.getResourceUri(guid);
			String target_uri;
			if (src_uri == null || src_uri.length() == 0) {
				continue;
			}

			target_uri = src_uri;
			/*
			if (newList.contains(guid)) {
				target_uri = src_uri;
			} else {
				target_uri = targetLibDoc.getResourceUri(guid); // the resource
				// might be
				// renamed
			}
			*/

			// Check the plugin.xmi file. If it exists, copy the folder to
			// the destination directory.
			final File src_file = importingLibDoc.getFileFromUri(src_uri);
			if (src_file.exists()) {
				final File target_file = targetLibDoc
						.getFileFromUri(target_uri);

				// if it's a configuration, only copy the file,
				// if it's a plugin, copy the whole directory

				if (data.getPluginInfo(guid) != null) {
					if (target_file.exists()) {
						SafeUpdateController.syncExec(new Runnable() {
							public void run() {
								DirCopy copy = new DirCopy(src_file
										.getParentFile(), target_file
										.getParentFile());
								fileCheckedOutStatus = copy.execute();
							}
						});
					} else {
						copyDir(src_file.getParentFile(), target_file
								.getParentFile());
					}
				} else if (data.getConfigInfo(guid) != null && DirCopy.needCopy(src_file, target_file)) {
					final List files = new ArrayList();
					if (target_file.exists()) {
						files.add(target_file.getAbsolutePath());
						SafeUpdateController.syncExec(new Runnable() {
							public void run() {
								fileCheckedOutStatus = FileModifyChecker
										.checkModify(files);
							}
						});
					}

					if (fileCheckedOutStatus == null
							|| fileCheckedOutStatus.isOK()) {
						ResourceHelper.copyFile(src_file, target_file);
					}
				}

				if ((fileCheckedOutStatus != null)
						&& !fileCheckedOutStatus.isOK()) {
					// log error
					SafeUpdateController.syncExec(new Runnable() {
						public void run() {
							String title = ImportResources.importPluginsWizard_title; //$NON-NLS-1$
							String msg = ImportResources.importPluginsWizard_ERR_Import_plugin; //$NON-NLS-1$
							new MsgDialog(ImportPlugin.getDefault())
									.displayError(title, msg,
											fileCheckedOutStatus);
						}
					});

					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Copies directories from "fromDir" to "toDir".
	 */
	public static void copyDir(File fromDir, File toDir) {
		Copy cp = new Copy();
		cp.setOverwrite(true);
		FileSet set = new FileSet();
		set.setExcludes(ConfigurationExportService.excludes);
		set.setDir(fromDir);
		cp.addFileset(set);
		cp.setTodir(toDir);
		cp.setProject(new Project());
		cp.execute();

	}

	// /**
	// * remove the plugin entry from the library document
	// *
	// * @param document
	// * LibraryDocument
	// * @param guid
	// * String guid of the plugin
	// */
	// private void removeExistingEntries(LibraryDocument document) {
	// // 1. Find the entries to be removed.
	// List removeList = new ArrayList();
	// PluginImportData.PluginInfo info;
	// for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
	// info = (PluginImportData.PluginInfo) it.next();
	// if ((info.existingPlugin != null) && info.selected) {
	// removeList.add(info.guid);
	// }
	// }
	//
	// PluginImportData.ConfiguarationInfo cinfo;
	// for (Iterator it = data.getConfigs().iterator(); it.hasNext();) {
	// cinfo = (PluginImportData.ConfiguarationInfo) it.next();
	// if ((cinfo.existingConfig != null) && cinfo.selected) {
	// removeList.add(cinfo.guid);
	// }
	// }
	//
	// // 2. Iterate the docuemnt and remove the entries.
	// document.removePlugins(removeList);
	// document.removeConfigurations(removeList);
	// document.removeResourceEntries(removeList);
	// }

	 /** 
	  * Validates selection.
	 */
	public String validateSelection() {
		data.getErrorInfo().clear();

		// Iterate the new plugins, make sure the base is included
		// either as an importing plugin, or is in the current library
		// get the method plugins in the current library.
		MethodLibrary library = LibraryService.getInstance()
				.getCurrentMethodLibrary();
		List plugins = (library == null) ? new ArrayList() : library
				.getMethodPlugins();
		List pluginids = new ArrayList();
		for (Iterator it = plugins.iterator(); it.hasNext();) {
			pluginids.add(((MethodPlugin) it.next()).getGuid());
		}

		// The base plug-ins MUST be either a selected one or an existing one
		// otherwise, can't import
		List basePlugins = new ArrayList();

		List newPlugins = new ArrayList();
		for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
			PluginImportData.PluginInfo info = (PluginImportData.PluginInfo) it
					.next();
			if (info.selected && (info.existingPlugin == null)) {
				newPlugins.add(info.guid);
				for (Iterator itb = info.usedPlugins.iterator(); itb.hasNext();) {
					Object base = itb.next();
					if (!basePlugins.contains(base)) {
						basePlugins.add(base);
					}
				}
			}
		}

		if (newPlugins.size() > 0) {
			for (Iterator it = basePlugins.iterator(); it.hasNext();) {
				String guid = (String) it.next();
				String uri = (String) data.basePluginUrlMap.get(guid);
				if (!newPlugins.contains(guid) && !pluginids.contains(guid)) {
					String message;
					if (uri != null && uri.length() > 0) {
						message = NLS.bind(ImportResources.PluginImportingService_MSG5, uri); 
					} else {
						message = ImportResources.PluginImportingService_MSG6; //$NON-NLS-1$
					}
					data.getErrorInfo().addError(message);

					if (uri == null || uri.length() == 0) {
						break;
					}
				}
			}
		}

		return data.getErrorInfo().getError();
	}

	private void scanLibraryFile(LibraryDocument document) {
		visitLibTag(document);
		visitResourceTag(document);
		data.validatePlugins();

		// Check base plug-in dependencies.
		for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
			PluginImportData.PluginInfo info = (PluginImportData.PluginInfo) it
					.next();
			if (info.existingPlugin == null) {
				for (Iterator itbase = info.usedPlugins.iterator(); itbase
						.hasNext();) {
					String guid = (String) itbase.next();
					if (!data.basePluginUrlMap.containsKey(guid)) {
						data.basePluginUrlMap.put(guid, ""); //$NON-NLS-1$
					}
				}
			}
		}
	}

	private void visitLibTag(LibraryDocument document) {
		// Reload the element mapping.
		NodeList nodes = document.getPlugins();
		for (int i = 0; i < nodes.getLength(); i++) {
			Element node = (Element) nodes.item(i);
			PluginImportData.PluginInfo pi = data.new PluginInfo();
			pi.guid = LibraryDocument.getGuid(node);
			data.getPlugins().add(pi);

			// Check with the current library, get the related information.
			loadExistingPluginInfo(pi);
		}

		// Remove the unneeded configurations.
		buildConfigInfoFromFiles();
	}

	private void visitResourceTag(LibraryDocument document) {
		NodeList nodes = document.getResourceDescriptors();
		for (int i = 0; i < nodes.getLength(); i++) {
			Element node = (Element) nodes.item(i);
			String guid = node.getAttribute(LibraryDocument.ATTR_id);
			String uri = node.getAttribute(LibraryDocument.ATTR_uri);

			// Load the plugin.xmi file for detail information.
			File file = document.getFileFromUri(uri);

			PluginImportData.PluginInfo pi = data.getPluginInfo(guid);
			if (pi != null) {
				if (file.exists()) {
					loadPluginInfo(file, pi);
				} else {
					// Remove the plug-in info entry since thias is not
					// a valid plug-in to import.
					data.removePluginInfo(guid);
				}
			} else {
				// if not plugin, might be a configuration
				PluginImportData.ConfiguarationInfo ci = data
						.getConfigInfo(guid);
				if (ci != null) {
					if (file.exists()) {
						loadConfigInfo(file, ci);
					}
				}
			}
		}
	}

	protected void loadConfigInfo(File source,
			PluginImportData.ConfiguarationInfo info) {
		try {
			Document document = XMLUtil.loadXml(source);
			Element root = document.getDocumentElement();

			Element configTag = null;
			if (root.getTagName().equals(
					"org.eclipse.epf.uma:MethodConfiguration")) //$NON-NLS-1$
			{
				configTag = root;
			} else {
				NodeList nodes = root
						.getElementsByTagName("org.eclipse.epf.uma:MethodConfiguration"); //$NON-NLS-1$
				if (nodes.getLength() > 0) {
					configTag = (Element) nodes.item(0);
				}
			}

			if (configTag != null) {
				info.name = configTag.getAttribute("name"); //$NON-NLS-1$
			}
		} catch (Exception e) {
			ImportPlugin.getDefault().getLogger().logError(e);
		}
	}

	protected void loadPluginInfo(File source, PluginImportData.PluginInfo info) {
		try {
			Document document = XMLUtil.loadXml(source);
			Element root = document.getDocumentElement();

			Element pluginTag = null;
			if (root.getTagName().equals("org.eclipse.epf.uma:MethodPlugin")) //$NON-NLS-1$
			{
				pluginTag = root;
			} else {
				NodeList nodes = root
						.getElementsByTagName("org.eclipse.epf.uma:MethodPlugin"); //$NON-NLS-1$
				if (nodes.getLength() > 0) {
					pluginTag = (Element) nodes.item(0);
				}
			}

			if (pluginTag != null) {
				info.name = pluginTag.getAttribute("name"); //$NON-NLS-1$
				info.version = LibraryDocument.getChildValue(pluginTag,
						"version"); //$NON-NLS-1$
				info.brief_desc = LibraryDocument.getChildValue(pluginTag,
						"briefDescription"); //$NON-NLS-1$
				info.authors = LibraryDocument.getChildValue(pluginTag,
						"authors"); //$NON-NLS-1$
				info.changeDate = LibraryDocument.getChildValue(pluginTag,
						"changeDate"); //$NON-NLS-1$
				info.url = source.toString();

				// Get the base plug-ins.
				NodeList nodes = pluginTag.getElementsByTagName("bases"); //$NON-NLS-1$
				for (int i = 0; i < nodes.getLength(); i++) {
					Element node = (Element) nodes.item(i);
					String guid = node.getAttribute(LibraryDocument.ATTR_href);

					int indx = guid.indexOf("#"); //$NON-NLS-1$
					if (indx > 0) {
						guid = guid.substring(indx + 1);
					} else {
						indx = guid.indexOf("uma://"); //$NON-NLS-1$
						if (indx >= 0) {
							guid = guid.substring(indx + 6);
						}
					}
					info.usedPlugins.add(guid);
				}
			}
		} catch (Exception e) {
			ImportPlugin.getDefault().getLogger().logError(e);
		}
	}

	private void loadExistingPluginInfo(PluginImportData.PluginInfo info) {
		MethodLibrary library = LibraryService.getInstance()
				.getCurrentMethodLibrary();
		List plugins = (library == null) ? new ArrayList() : library
				.getMethodPlugins();
		for (Iterator it = plugins.iterator(); it.hasNext();) {
			MethodPlugin plugin = (MethodPlugin) it.next();
			if (plugin.getGuid().equals(info.guid)) {
				info.existingPlugin = plugin;
			}
		}
	}

	private void loadExistingConfigInfo(PluginImportData.ConfiguarationInfo info) {
		MethodConfiguration[] configs = LibraryServiceUtil
				.getMethodConfigurations(LibraryService.getInstance()
						.getCurrentMethodLibrary());
		if (configs == null || configs.length == 0) {
			return;
		}

		for (int i = 0; i < configs.length; i++) {
			MethodConfiguration config = configs[i];
			if (config.getGuid().equals(info.guid)) {
				info.existingConfig = config;
			}
		}
	}

	/**
	 * Replaces the guid of the old method library with the new one.
	 * <p>
	 * Search for the following files: library.xmi, plugin.xmi, model.xmi.
	 */
	private void fixLibraryGuid(File path, String oldGuid, String newGuid) {
		if (!path.isDirectory()) {
			return;
		}

		File[] files = path.listFiles(new FileFilter() {

			public boolean accept(File f) {

				if (f.isDirectory()) {
					return true;
				}

				String name = f.getName();
				return name.equals("library.xmi") || name.equals("plugin.xmi") || name.equals("model.xmi"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
		});

		if (files == null || files.length == 0) {
			return;
		}

		for (int i = 0; i < files.length; i++) {
			if (files[i].isDirectory()) {
				fixLibraryGuid(files[i], oldGuid, newGuid);
			} else {
				// Read in the file, update it and save the file.
				try {
					String source = FileUtil.readFile(files[i],
							FileUtil.ENCODING_UTF_8).toString();
					if (source.indexOf(oldGuid) >= 0) {
						// TODO: This is a regexp repalcement, is it safe?
						source = source.replaceAll(oldGuid, newGuid);

						FileUtil.writeUTF8File(files[i].getAbsolutePath(),
								source);
					}

				} catch (IOException e) {
					ImportPlugin.getDefault().getLogger().logError(e);
				}
			}
		}
	}
	
	private void merge(LibraryDocument targetLibDoc) throws Exception {
		//Copy files only as newMergeScheme = true
		importEntries(targetLibDoc);
		
		MethodLibrary lib = LibraryService.getInstance().getCurrentMethodLibrary();
		Resource res0 = lib.eResource();
		ResourceManager resMgr0 = (ResourceManager) MultiFileSaveUtil.getResourceManager(res0);
		ResourceSet resSet = res0.getResourceSet();
		
		mergePlugins(targetLibDoc, lib, resMgr0, resSet);		
		mergeConfigs(targetLibDoc, lib, resMgr0, resSet);
		
		lib.eResource().setModified(true);
		
		//LibraryUtil.saveLibrary(lib, false, false);
		ILibraryPersister.FailSafeMethodLibraryPersister persister = LibraryServiceUtil.getCurrentPersister().getFailSafePersister();
		try {
			persister.save(lib.eResource());
			persister.commit();
		} catch (Exception e) {
			persister.rollback();
			e.printStackTrace();
		}	
		
		//fixLibraryGuid(targetLibDoc.getFile().getParentFile(), importingLibDoc
		//		.getLibraryGuid(), targetLibDoc.getLibraryGuid());
		
		LibraryService.getInstance().reopenCurrentMethodLibrary();
	}

	private void mergePlugins(LibraryDocument targetLibDoc, MethodLibrary lib, ResourceManager resMgr0, ResourceSet resSet) {
		List existingPluginGuids = null;
		for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
			PluginImportData.PluginInfo info = (PluginImportData.PluginInfo) it.next();
			if (info.selected && info.existingPlugin != null) {
				if (existingPluginGuids == null) {
					existingPluginGuids = new ArrayList();
				}
				existingPluginGuids.add(info.guid);
			}
		}
		
		Map pgToRgMap = importingLibDoc.buildPluginGuidToResMgrGuidMap(existingPluginGuids);				
		
		for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
			PluginImportData.PluginInfo info = (PluginImportData.PluginInfo) it.next();
			if (info.selected && info.existingPlugin == null) {
				mergeElement(info.guid, targetLibDoc, lib, resMgr0, resSet, lib.getMethodPlugins());
			} else if (info.selected && pgToRgMap != null) {	//151786
				Resource res = info.existingPlugin.eResource();
				ResourceManager resMgr = (ResourceManager) MultiFileSaveUtil.getResourceManager(res);
				String existingGuid = resMgr.getGuid();
				String importedGuid = (String) pgToRgMap.get(info.guid);
				if (importedGuid != null && !importedGuid.equals(existingGuid)) {
					resMgr.setGuid(importedGuid);
				}
			}
		}
	}
	
	private void mergeConfigs(LibraryDocument targetLibDoc, MethodLibrary lib, ResourceManager resMgr0, ResourceSet resSet) {
		for (Iterator it = data.getConfigs().iterator(); it.hasNext();) {
			PluginImportData.ConfiguarationInfo info = (PluginImportData.ConfiguarationInfo) it.next();
			if (info.selected && info.existingConfig == null) {
				mergeElement(info.guid, targetLibDoc, lib, resMgr0, resSet, lib.getPredefinedConfigurations());
			}					
		}
	}
	
	private void mergeElement(String guid, LibraryDocument targetLibDoc, 
			MethodLibrary lib, ResourceManager resMgr0, ResourceSet resSet, List elements){
		String src_uri = importingLibDoc.getResourceUri(guid);
		if (src_uri == null || src_uri.length() == 0) {
			return;
		}
		File target_file = targetLibDoc.getFileFromUri(src_uri);
		String path = target_file.getAbsolutePath();
		
		URI uri = URI.createFileURI(path);
		Resource res = resSet.getResource(uri, true);
		MethodElement element = PersistenceUtil.getMethodElement(res);
		elements.add(element);		
		
		MultiFileSaveUtil.registerWithResourceManager(resMgr0, element, uri);
		ResourceManager resMgr = (ResourceManager) MultiFileSaveUtil.getResourceManager(res);
		if (resMgr != null) {
			resMgr0.getSubManagers().add(resMgr);
		}
	}		
	
	private void buildConfigInfoFromFiles() {	
		File copiedLibPath = upGradeInfo == null ? null : upGradeInfo.getCopiedLibFile();
		File importingLibPath = copiedLibPath == null ? new File(data.llData.getParentFolder()
				+ File.separator + LibraryDocument.exportFile) : copiedLibPath;
		File configDir = new File(importingLibPath.getParent(), MultiFileSaveUtil.METHOD_CONFIGURATION_FOLDER_NAME);
		
		LibraryDocument.ConfigDocVisitor visitor = new LibraryDocument.ConfigDocVisitor() {
			public void visit(File file, Element node) {
				PluginImportData.ConfiguarationInfo ci = data.new ConfiguarationInfo();
				ci.guid = node.getAttribute(LibraryDocument.ATTR_guid);
				ci.name = node.getAttribute("name"); //$NON-NLS-1$
				String uri = MultiFileSaveUtil.METHOD_CONFIGURATION_FOLDER_NAME + File.separator + file.getName();
				importingLibDoc.addToGuidToUriMap(ci.guid, uri);
				data.getConfigs().add(ci);
				// Check with the current library, get the related information.
				loadExistingConfigInfo(ci);
				if (ci.existingConfig != null) {
					URI resUri = ci.existingConfig.eResource().getURI();
					uri = MultiFileSaveUtil.METHOD_CONFIGURATION_FOLDER_NAME + File.separator + resUri.lastSegment();
					uri = targetLibDoc.decodeUri(uri);
					targetLibDoc.addToGuidToUriMap(ci.guid, uri);
				}
			}
		};
		
		LibraryDocument.visitConfigFiles(configDir, visitor);				
	}
	
	private void ensureUniqueNames(List elements) {
		if (elements.isEmpty()) {
			return;
		}
		Map nameMap = new HashMap();
		for (int i=0; i < elements.size(); i++) {
			MethodElement elem = (MethodElement) elements.get(i);
			nameMap.put(elem.getName(), elem);
		}
		
		List importedList = new ArrayList();
		List importedExistList = new ArrayList();
		if (elements.get(0) instanceof MethodPlugin) {
			for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
				PluginImportData.PluginInfo info = (PluginImportData.PluginInfo) it.next();
				if (info.selected) {
					if (info.existingPlugin == null || 
							!info.existingPlugin.getName().equals(info.name)) {
						importedList.add(info.name);
						if (info.existingPlugin != null) {
							importedExistList.add(info);
						}
					}
				}
			}
		} else {
			for (Iterator it = data.getConfigs().iterator(); it.hasNext();) {
				PluginImportData.ConfiguarationInfo info = (PluginImportData.ConfiguarationInfo) it.next();
				if (info.selected) {
					if (info.existingConfig == null || 
							!info.existingConfig.getName().equals(info.name)) {
						importedList.add(info.name);
						if (info.existingConfig != null) {
							importedExistList.add(info);
						}
					}
				}				
			}
		}
		for (int i=0; i<importedList.size(); i++) {
			String name = (String) importedList.get(i);
			String renamed = name;
			while (nameMap.containsKey(renamed)) {
				renamed += "_renamed";
			}
			if (renamed != name) {
				MethodElement elem = (MethodElement) nameMap.get(name);
				LibraryView.runRename(elem, renamed);
			}			
		}				
		for (int i=0; i<importedExistList.size(); i++) {
			Object info = importedExistList.get(i);
			MethodElement elem = info instanceof PluginImportData.PluginInfo ? 
					(MethodElement)((PluginImportData.PluginInfo) info).existingPlugin :
					(MethodElement)((PluginImportData.ConfiguarationInfo) info).existingConfig;
			String newName = info instanceof PluginImportData.PluginInfo ? 
					(String)((PluginImportData.PluginInfo) info).name :
					(String)((PluginImportData.ConfiguarationInfo) info).name;								
			LibraryView.runRename(elem, newName);		
		}	
		
		
		
	}
	
}