//------------------------------------------------------------------------------
// 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.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

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
 * @author Weiping Lu
 * @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();
		Map pluginids = new HashMap();
		for (Iterator it = plugins.iterator(); it.hasNext();) {
			MethodPlugin plugin = (MethodPlugin) it.next();
			pluginids.put(plugin.getGuid(), plugin);
		}

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

		Set newPlugins = new HashSet();
		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.containsKey(guid)) {
					String message;
					if (uri != null && uri.length() > 0) {
						message = NLS.bind(ImportResources.PluginImportingService_MSG5, uri); 
					} else {
						Map<String, String> guidToPlugNameMap = importingLibDoc.getGuidToPlugNameMap();
						String pluginName = guidToPlugNameMap == null ? null : guidToPlugNameMap.get(guid);
						if (pluginName == null || pluginName.length() == 0) {
							message = ImportResources.PluginImportingService_MSG6; 
						} else {
							message = NLS.bind(ImportResources.PluginImportingService_MSG5, 
									pluginName + ", " + guid); 		//$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().toUpperCase(), 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.toUpperCase())) {
				renamed += "_renamed";
			}
			if (renamed != name) {
				MethodElement elem = (MethodElement) nameMap.get(name.toUpperCase());
				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);		
		}	
		
		
		
	}
	
}