//------------------------------------------------------------------------------
// 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.library.layout;

import java.io.File;
import java.util.Collection;
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 java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.ILibraryManager;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.configuration.DefaultElementRealizer;
import org.eclipse.epf.library.configuration.ElementRealizer;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.util.ConfigurableComposedAdapterFactory;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.diagram.IActivityDiagramService;
import org.eclipse.epf.library.layout.elements.AbstractElementLayout;
import org.eclipse.epf.library.layout.elements.AbstractProcessElementLayout;
import org.eclipse.epf.library.layout.elements.GeneralLayout;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodElementProperty;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.util.UmaUtil;


/**
 * @author Jinhua Xi
 * @since 1.0
 */
public class ElementLayoutManager {

	private static final String PACKAGE_NAME = ElementLayoutManager.class
			.getPackage().getName();

	private static final String default_config_path = "noconfig"; //$NON-NLS-1$

	private boolean isPublishingMode = false; // default to browsing mode
	
	private String publish_dir = null;

	private MethodConfiguration config = null;

	private IActivityDiagramService diagramService = null;
	
	// need to seperate the adapter factory form content and diagram
	// diagram adaptor factory should not be rolled up
	private LayoutAdapterFactory contentLayoutAdapterFactory = null;
	private LayoutAdapterFactory diagramLayoutAdapterFactory = null;
	
	// cache the suppression object for publishing model only
	// map of proc guid to Suppresiion object	
	private Map supressionMap = null;
	
	private IContentValidator validator = null;
	
	private ElementRealizer realizer = null;
	
	private Map<String, String> toRenamePluginFolderMap;
	
	// the layout extensions. each extension is identified by the property id of the configuration
	private Map<String, LayoutExtension> layoutExtensions = new HashMap<String, LayoutExtension>();
	
	public boolean isPublishingMode()
	{
		return this.isPublishingMode;
	}
	
	public ElementLayoutManager() {
		this(null, null, null, false);
		buildPublishDir(null);
	}

	public ElementLayoutManager(MethodConfiguration config) {
		this(config, null, null, false);
	}

	public ElementLayoutManager(MethodConfiguration config, String publishdir, IContentValidator validator, boolean isPublishingMode) {
		this.validator = validator;
		this.isPublishingMode = isPublishingMode;
		
		if (config != null) {
			this.config = config;
		}

		if (isPublishingMode) {
			buildPublishDir(publishdir);
		}

		contentLayoutAdapterFactory = new LayoutAdapterFactory(this.config);
		diagramLayoutAdapterFactory = new LayoutAdapterFactory(this.config);
		
		//	load the layout extensions for this configuration
		loadLayoutExtensions();
	}

	private boolean publishDirBuilt = false;
	public void buildPublishDir(String publishdir) {
		if (publishDirBuilt) {
			return;
		}
		publishDirBuilt = true;
		
		if (publishdir == null) {
			publishdir = LayoutResources.getDefaultPublishDir();
			if (!publishdir.endsWith(File.separator)) {
				publishdir += File.separator;
			}

			// also append the configuration path
			if (this.config == null) {
				publishdir += default_config_path;
			} else {
				String str = StrUtil.removeSpecialCharacters(this.config.getName());
				if ( str == "" ) { //$NON-NLS-1$
					str = Integer.toHexString(this.config.toString().hashCode());
				}
				publishdir += str;
			}
		}

		setPublishDir(publishdir);
	}

	private void loadLayoutExtensions() {
		if ( config == null ) {
			return;
		}
		
		// load the layout extensions for this configuration
		List props = config.getMethodElementProperty();
		if ( props != null && props.size() > 0 ) {
			for (Iterator itp = props.iterator(); itp.hasNext(); ) {
				MethodElementProperty prop = (MethodElementProperty)itp.next();
				String id = prop.getName();
				LayoutExtension ext= LayoutExtensionFactory.getInstance().createExtension(id);
				if ( ext != null ) {
					ext.init(this);
					layoutExtensions.put(id, ext);
				}
				
			}
		}		
	}
	
	/**
	 * Returns the content validator.
	 */
	public IContentValidator getValidator() {
		if (validator == null) {
			validator = new DefaultContentValidator(getPublishDir());
		}
		return validator;
	}
	
	public ElementRealizer getElementRealizer() {
		if ( realizer == null ) {
			realizer = DefaultElementRealizer.newElementRealizer(config);
			realizer.setFilter(contentLayoutAdapterFactory.getFilter());
		}
		
		return realizer;		
	}
	
	public void setElementRealizer(ElementRealizer realizer) {
		this.realizer = realizer;		
	}
	
	public ConfigurableComposedAdapterFactory getWBSAdapterFactory() {
		return contentLayoutAdapterFactory.wbsAdapterFactory;
	}

	public ConfigurableComposedAdapterFactory getTBSAdapterFactory() {
		return contentLayoutAdapterFactory.tbsAdapterFactory;
	}

	public ConfigurableComposedAdapterFactory getWPBSAdapterFactory() {
		return contentLayoutAdapterFactory.wpbsAdapterFactory;
	}

	public ConfigurableComposedAdapterFactory getCBSAdapterFactory() {
		return contentLayoutAdapterFactory.cbsAdapterFactory;
	}

	public ConfigurableComposedAdapterFactory getDiagramAdapterFactory() {
		return diagramLayoutAdapterFactory.wbsAdapterFactory;
	}
	
	public void setActivityDiagramService(IActivityDiagramService diagramService) {
		this.diagramService = diagramService;
	}

	public IActivityDiagramService getActivityDiagramService() {
		return this.diagramService;
	}

	public Suppression getSuppression(Process proc)
	{
		Suppression sup = null;
		if ( isPublishingMode)
		{
			if ( supressionMap == null )
			{
				supressionMap = new HashMap();
			}
			String guid = proc.getGuid();
			sup = (Suppression)supressionMap.get(guid);
			if ( sup == null )
			{
				sup = createSuppression(proc);
				supressionMap.put(guid, sup);
			}
		}
		else
		{
			sup = createSuppression(proc);
		}
		
		return sup;
	}
	
	public void prepareAdaptorFactoriesForProcess(Process proc)
	{
		// need to iterate the adaptor factory to generate the adaptor tree
		prepareAdapterfactoryFor(getCBSAdapterFactory(), proc);
		prepareAdapterfactoryFor(getTBSAdapterFactory(), proc);
		prepareAdapterfactoryFor(getWBSAdapterFactory(), proc);
		prepareAdapterfactoryFor(getWPBSAdapterFactory(), proc);
	}
	
	private void prepareAdapterfactoryFor(
			ComposedAdapterFactory adapterFactory, Object obj) {
		if (obj == null || adapterFactory == null) {
			return;
		}

		ITreeItemContentProvider provider = null;

		if (obj instanceof ITreeItemContentProvider) {
			provider = (ITreeItemContentProvider) obj;
		} else {
			provider = (ITreeItemContentProvider) adapterFactory.adapt(obj,
					ITreeItemContentProvider.class);
		}

		if (provider != null) {
			Collection items = provider.getChildren(obj);
			for (Iterator it = items.iterator(); it.hasNext();) {
				Object rawitem = it.next();

				MethodElement item = (MethodElement) LibraryUtil
						.unwrap(rawitem);
				if ((item instanceof Activity)) {
					prepareAdapterfactoryFor(adapterFactory, rawitem);
				}
			}
		}
	}
	
	private IElementLayout createLayout(MethodElement element) {
		
		// if the element is an activity, we need to fined the path to the process
		String path = null;
		Process owningProc = null;
		if ( element instanceof Activity )
		{
			Activity act = (Activity)element;
			path = AbstractProcessElementLayout.getPath(act);
			owningProc = TngUtil.getOwningProcess(act);
		}
		
		return createLayout(element, owningProc, path);
	}

	public IElementLayout createLayout(MethodElement element,
			Process owningProc, String path) {
		AbstractElementLayout layout = null;

		String className;
		if (ConfigurationHelper.isDescriptionElement(element)) {
			className = "ContentDescription"; //$NON-NLS-1$
		} else if (element instanceof Activity) {
			className = "Activity"; //$NON-NLS-1$
		} else if ((element instanceof WorkBreakdownElement)
				&& !(element instanceof TaskDescriptor)) {
			className = "WorkBreakdownElement"; //$NON-NLS-1$  // taskdescriptor has it's own layout
		} else {
			Class i[] = element.getClass().getInterfaces();
			if (i != null && i.length == 1) {
				className = i[0].getName();
			} else {
				className = element.getClass().getName();
			}

			int index = className.lastIndexOf("."); //$NON-NLS-1$
			if (index >= 0) {
				className = className.substring(index + 1);
			}
		}

		className = PACKAGE_NAME + ".elements." + className + "Layout"; //$NON-NLS-1$ //$NON-NLS-2$

		try {
			Class c = Class.forName(className);
			if (c != null) {
				layout = (AbstractElementLayout) c.newInstance();
			}
		} catch (Exception ex) {
			// ex.printStackTrace();
		}

		if (layout == null) {
			// System.out.println("Layout class '" + className + "' for element
			// '" + element.getName() + "' not defined. Use GeneralLayout");
			layout = new GeneralLayout();
		}

		if (layout instanceof AbstractProcessElementLayout) {
			((AbstractProcessElementLayout) layout).init(this, element,
					owningProc, path);
		} else {
			layout.init(this, element);
		}

		return layout;
	}

	public IElementLayout getLayout(MethodElement element, boolean create) {
		// String id = element.getGuid();
		IElementLayout layout = null; // (IElementLayout)layoutMap.get(id);
		if ((layout == null) && create) {
			layout = createLayout(element);
			// layoutMap.put(id, layout);
		}

		return layout;
	}

	private static final Pattern p_parameters = Pattern
			.compile(
					"\\?proc=(.*?)&path=(.*)?", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public IElementLayout getLayout(String url) {

		Process owningProc = null;
		String path = null;

		Matcher m = p_parameters.matcher(url);
		if (m.find()) {
			String proc = m.group(1);
			path = m.group(2);
			ILibraryManager manager = LibraryService.getInstance()
			.getCurrentLibraryManager();
			if (manager != null) {
				owningProc = (Process) manager.getMethodElement(
						proc);
			}
		}

		// MethodElement element = (MethodElement)urlMap.get(url);
		MethodElement element = ResourceHelper.getElementFromFileName(url);
		if (element != null) {
			return createLayout(element, owningProc, path);
		} else {
			System.out.println("Can't find element for url '" + url + "'"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		return null;

	}

	public static String getQueryString(String proc, String path) {
		return "?" + ResourceHelper.URL_PARAMETER_PROCESS + "=" + proc + "&" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				+ ResourceHelper.URL_PARAMETER_PATH + "=" + path; //$NON-NLS-1$
	}

	public MethodConfiguration getConfiguration() {
		return this.config;
	}

	public void setPublishDir(String path) {
		this.publish_dir = path;
		if ( !this.publish_dir.endsWith(File.separator) ) {
			this.publish_dir += File.separator;
		}

		// initialize publishing site if needed
		init_publishingSite();

	}

	public String getPublishDir() {
		return this.publish_dir;
	}

	private void init_publishingSite() {
		if ( BrowsingLayoutSettings.INSTANCE.needUpdate(publish_dir) ) {
//			if ( LibraryPlugin.getDefault().isDebugging() ) {
				System.out
						.println("Begin initializing publishing site: " + publish_dir); //$NON-NLS-1$
//			}
			
			// copy the layout files from plugin layout to publishign site
			LayoutResources.copyLayoutFiles(publish_dir);
	
			if ( LibraryPlugin.getDefault().isDebugging() ) {
				System.out.println("End initializing publishing site: " + publish_dir); //$NON-NLS-1$
			}
		}
	}

//	public void copyLibraryResources() {
//		if ( LibraryPlugin.getDefault().isDebugging() ) {
//			System.out
//					.println("Begin copying library resources to publishing site: " + publish_dir); //$NON-NLS-1$
//		}
//		
//		// copy library resources from library to publishing site
//		File libRoot = new File(LibraryService.getInstance().getCurrentMethodLibraryPath());
//		if (libRoot != null) {
//			LayoutResources.copyDir(libRoot.getPath(), publish_dir);
//		}
//
//		if ( LibraryPlugin.getDefault().isDebugging() ) {
//			System.out
//					.println("End copying library resources to publishing site: " + publish_dir); //$NON-NLS-1$
//		}
//	}

	public void clear() {
		// layoutMap.clear();
		
		diagramService = null;
		
		if ( supressionMap != null )
		{
			supressionMap.clear();
		}
		
		layoutExtensions.clear();
		layoutExtensions = null;
		
		contentLayoutAdapterFactory.clear();
		diagramLayoutAdapterFactory.clear();
		
		if ( validator != null )
		{
			validator.dispose();
			validator = null;
		}
		
		if ( realizer != null ) {
			realizer.dispose();
			realizer = null;
		}
		
		if ( contentLayoutAdapterFactory != null ) {
			contentLayoutAdapterFactory.clear();
			contentLayoutAdapterFactory = null;			
		}
		
		if ( diagramLayoutAdapterFactory != null ) {
			diagramLayoutAdapterFactory.clear();
			diagramLayoutAdapterFactory = null;			
		}
		 
		toRenamePluginFolderMap = null;
	}

	public class LayoutAdapterFactory
	{
		public ConfigurableComposedAdapterFactory wbsAdapterFactory = null;
		public ConfigurableComposedAdapterFactory tbsAdapterFactory = null;
		public ConfigurableComposedAdapterFactory wpbsAdapterFactory = null;
		public ConfigurableComposedAdapterFactory cbsAdapterFactory = null;

		ProcessAdapterFactoryFilter configurator = null;
		
		public LayoutAdapterFactory(MethodConfiguration methodConfig)
		{
			// create adapt factories
			//
			if(isPublishingMode()) {
				wbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
				.createPublishingWBSAdapterFactory();
				tbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
				.createPublishingTBSAdapterFactory();
				wpbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
				.createPublishingWPBSAdapterFactory();
				cbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
				.createPublishingCBSAdapterFactory();
			}
			else {
				wbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
				.createWBSComposedAdapterFactory();
				tbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
				.createTBSComposedAdapterFactory();
				wpbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
				.createWPBSComposedAdapterFactory();
				cbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
				.createProcessComposedAdapterFactory();
			}

			// set configuration filter
			configurator = new ProcessAdapterFactoryFilter(methodConfig, this) {
				
				@Override
				public ElementRealizer getRealizer() {
					ElementRealizer realizer = ElementLayoutManager.this.getElementRealizer();
					if (realizer == null) {
						realizer = super.getRealizer();
					}
					return realizer;
				}
			};
			
			wbsAdapterFactory.setFilter(configurator);
			tbsAdapterFactory.setFilter(configurator);
			wpbsAdapterFactory.setFilter(configurator);
			cbsAdapterFactory.setFilter(configurator);		
		}
		
		public IFilter getFilter() {
			return configurator;
		}
		
		public void clear()
		{
						
			if (wbsAdapterFactory != null) {
				wbsAdapterFactory.setFilter(null);
				wbsAdapterFactory.dispose();
				wbsAdapterFactory = null;
			}

			if (tbsAdapterFactory != null) {
				tbsAdapterFactory.setFilter(null);
				tbsAdapterFactory.dispose();
				tbsAdapterFactory = null;
			}

			if (wpbsAdapterFactory != null) {
				wpbsAdapterFactory.setFilter(null);
				wpbsAdapterFactory.dispose();
				wpbsAdapterFactory = null;
			}

			if (cbsAdapterFactory != null) {
				cbsAdapterFactory.setFilter(null);
				cbsAdapterFactory.dispose();
				cbsAdapterFactory = null;
			}
			
			if ( configurator != null ) {
				configurator.dispose();
				configurator = null;
			}
		}
	}
	
	private Suppression createSuppression(Process proc) {
		// check if there are extensions
		if ( layoutExtensions != null && layoutExtensions.size() > 0 ) {
			for ( Iterator<LayoutExtension> it = layoutExtensions.values().iterator(); it.hasNext(); ) {
				LayoutExtension ext = it.next();
				Suppression sup = ext.getSuppression(proc);
				if ( sup != null ) {
					return sup;
				}
			}
		}
		
		return new Suppression(proc);
	}
	
	public void prepareElementPathAdjustment() {
		String fChars = BrowsingLayoutSettings.INSTANCE.getForbiddenUrlChars();
		if (fChars == null || fChars.trim().length() == 0) {			//if flag is not set
			return;
		}
		MethodConfiguration c = getConfiguration();
		if (c == null) {
			return;
		}
		
		toRenamePluginFolderMap = new HashMap<String, String>();
		Set<String> usedNameSet = new HashSet<String>();
		MethodLibrary lib = UmaUtil.getMethodLibrary(c);
		for (MethodPlugin p : lib.getMethodPlugins()) {
			usedNameSet.add(p.getName());
		}
		
		List<MethodPlugin> plugins = c.getMethodPluginSelection();
		Set<String> forbidenChars = new HashSet<String>();
		for (int i = 0; i < fChars.length(); i++) {			
			String str = String.valueOf((fChars.charAt(i)));
			if (str.trim().length() > 0) {
				forbidenChars.add(str);
			}
		}
		for (MethodPlugin plugin : plugins) {
			String name = plugin.getName();
			String replacingName = getReplacingName(name, forbidenChars);
			if (! name.equals(replacingName)) {
				replacingName = getUniqueName(replacingName, usedNameSet);
				usedNameSet.add(replacingName);
				toRenamePluginFolderMap.put(plugin.getName(), replacingName);
			}
					}
		if (toRenamePluginFolderMap.isEmpty()) {
			toRenamePluginFolderMap = null;
		}
	}
	
	private String getReplacingName(String name, Set<String> forbidenChars) {
		StringBuffer b = new StringBuffer();
		boolean modified = false;
		for (int i = 0; i < name.length(); i++) {			
			String str = String.valueOf((name.charAt(i)));
			if (forbidenChars.contains(str)) {
				b.append("_"); //$NON-NLS-1$ 
				modified = true;
			} else {
				b.append(str);
			}			
		}
		return modified ? b.toString() : name;
	}
	
	public String getAdjustedElementPath(String elementPath) {
		if (toRenamePluginFolderMap == null) {
			return elementPath;
		}
		String pluginName = getPluginName(elementPath);
		if (pluginName == null) {
			return elementPath;
		}
		String replacingPluginName = toRenamePluginFolderMap.get(pluginName);
		if (replacingPluginName == null) {
			return elementPath;
		}
					
		return elementPath.replaceFirst(pluginName, replacingPluginName);
	}

	private String getUniqueName(String name, Set<String> usedNameSet) {
		String uniqueName = name;
		int i = 0;
		while(usedNameSet.contains(uniqueName)) {
			i++;
			uniqueName = name + i;
		}
		
		return uniqueName;
	}
	
	private String getPluginName(String elementPath) {
		int ix = elementPath.indexOf("/");
		if (ix > 0) {
			return elementPath.substring(0, ix);
		}		
		return null;
	}
	
	public String getAdjustedElementPathStringValue(String source) {
		if (toRenamePluginFolderMap == null) {
			return source;
		}
		
		boolean localDebug = false;
		String str = getAdjustedElementPathStringValue(source, ResourceHelper.p_link_ref);
		str = getAdjustedElementPathStringValue(str, ResourceHelper.p_area_ref);
		if (localDebug) {
			if (str != source) {
				System.out.println("LD> original value: " + source);	//$NON-NLS-1$
				System.out.println("");	//$NON-NLS-1$
				System.out.println("LD> modified value: " + str);	//$NON-NLS-1$
			}
			System.out.println("");	//$NON-NLS-1$
		}		
		
		return str;
	}
		
	private String getAdjustedElementPathStringValue(String source, Pattern pattern) {
		boolean localDebug = false;
		
		boolean modified = false;
		StringBuffer sb = new StringBuffer();
		Matcher m = pattern.matcher(source);

		while (m.find()) {
			String text = m.group();
			String replacement = text;			
			
			Map attributeMap = ResourceHelper.getAttributesFromLink(pattern, text);
			
			if (localDebug) {
				System.out.println("LD> text:      " + text);					//$NON-NLS-1$
				System.out.println("LD> attributeMap: " + attributeMap);		//$NON-NLS-1$
			}
			
			String href = attributeMap == null ? null : (String) attributeMap.get(ResourceHelper.TAG_ATTR_HREF);
			
			int ix0 = -1;
			int ix1 = -1;
			if (href != null) {
				//example: href="./../../a.b.c.d.e/roles/new_role-1_BA944608.html"
				//						 |        |
				//						ix0       |
				//						         ix1
				ix0 = href.lastIndexOf("../");		//$NON-NLS-1$
				if (ix0 > 0) {
					ix0 += 3;			
					ix1 = href.substring(ix0).indexOf("/");		//$NON-NLS-1$
					if (ix1 > 0) {
						ix1 += ix0;
					}
				}
			}
			
			if (ix0 >= 0 && ix1 > ix0) {
				String replaced = href.substring(ix0, ix1);
				String replacing = toRenamePluginFolderMap.get(replaced);
				if (replacing != null) {
					replacement = text.replace(replaced, replacing);
					if (localDebug) {
						System.out.println("LD>  replaced: " + replaced);	//$NON-NLS-1$
						System.out.println("LD> replacing: " + replacing);	//$NON-NLS-1$
						System.out.println("");								//$NON-NLS-1$
					}
					
					modified = true;
				}
			}			
			m.appendReplacement(sb, Matcher.quoteReplacement(replacement));				
		}
		m.appendTail(sb);
		
		return modified ? sb.toString() : source;
	}
	
	public void handlePluginFolderRename() {
		if (toRenamePluginFolderMap == null) {
			return;
		}
		String topDirStr = getPublishDir();
	    for (Map.Entry<String, String> entry : toRenamePluginFolderMap.entrySet()) {
	    	File oldPluginFolder = new File(topDirStr, entry.getKey());
	    	if (oldPluginFolder.isDirectory()) {
	    		File newPluginFolder = new File(topDirStr, entry.getValue());
	    		boolean b = oldPluginFolder.renameTo(newPluginFolder);
	    		if (! b) {
	    			FileUtil.copyDir(oldPluginFolder, newPluginFolder);
	    			FileUtil.deleteAllFiles(oldPluginFolder.getAbsolutePath());
	    			oldPluginFolder.delete();
	    		}
	    	}
	    }
	}
	
}

