/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Carsten Pfeiffer <carsten.pfeiffer@gebit.de> - CompareUIPlugin.getCommonType() returns null if left or right side is not available - https://bugs.eclipse.org/311843
 *     Stefan Xenos <sxenos@gmail.com> (Google) - bug 448968 - Add diagnostic logging
 *     Stefan Dirix <sdirix@eclipsesource.com> - bug 473847: Minimum E4 Compatibility of Compare
 *******************************************************************************/
package org.eclipse.compare.internal;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.IResourceProvider;
import org.eclipse.compare.IStreamContentAccessor;
import org.eclipse.compare.IStreamMerger;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.internal.core.ComparePlugin;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.compare.structuremergeviewer.IStructureCreator;
import org.eclipse.compare.structuremergeviewer.StructureDiffViewer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.debug.DebugOptionsListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

/**
 * The Compare UI plug-in defines the entry point to initiate a configurable
 * compare operation on arbitrary resources. The result of the compare
 * is opened into a compare editor where the details can be browsed and
 * edited in dynamically selected structure and content viewers.
 * <p>
 * The Compare UI provides a registry for content and structure compare viewers,
 * which is initialized from extensions contributed to extension points
 * declared by this plug-in.
 * <p>
 * This class is the plug-in runtime class for the
 * <code>"org.eclipse.compare"</code> plug-in.
 * </p>
 */
public final class CompareUIPlugin extends AbstractUIPlugin {

	static class CompareRegistry<T> {
		private final static String ID_ATTRIBUTE= "id"; //$NON-NLS-1$
		private final static String EXTENSIONS_ATTRIBUTE= "extensions"; //$NON-NLS-1$
		private final static String CONTENT_TYPE_ID_ATTRIBUTE= "contentTypeId"; //$NON-NLS-1$

		private HashMap<String, T> fIdMap;	// maps ids to data
		private HashMap<String, List<T>> fExtensionMap;	// multimap: maps extensions to list of data
		private HashMap<IContentType, List<T>> fContentTypeBindings; // multimap: maps content type bindings to list of data


		void register(IConfigurationElement element, T data) {
			String id= element.getAttribute(ID_ATTRIBUTE);
			if (id != null) {
				if (fIdMap == null)
					fIdMap= new HashMap<>();
				fIdMap.put(id, data);
			}

			String types= element.getAttribute(EXTENSIONS_ATTRIBUTE);
			if (types != null) {
				if (fExtensionMap == null)
					fExtensionMap= new HashMap<>();
				StringTokenizer tokenizer= new StringTokenizer(types, ","); //$NON-NLS-1$
				while (tokenizer.hasMoreElements()) {
					String extension= tokenizer.nextToken().trim();
					List<T> l = fExtensionMap.get(normalizeCase(extension));
					if (l == null)
						fExtensionMap.put(normalizeCase(extension),	l = new ArrayList<>());
					l.add(data);
				}
			}
		}

		void createBinding(IConfigurationElement element, String idAttributeName) {
			String type= element.getAttribute(CONTENT_TYPE_ID_ATTRIBUTE);
			String id= element.getAttribute(idAttributeName);
			if (id == null)
				logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.targetIdAttributeMissing", idAttributeName)); //$NON-NLS-1$
			if (type != null && id != null && fIdMap != null) {
				T o= fIdMap.get(id);
				if (o != null) {
					IContentType ct= fgContentTypeManager.getContentType(type);
					if (ct != null) {
						if (fContentTypeBindings == null)
							fContentTypeBindings= new HashMap<>();
						List<T> l = fContentTypeBindings.get(ct);
						if (l == null)
							fContentTypeBindings.put(ct, l = new ArrayList<>());
						l.add(o);
					} else {
						logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.contentTypeNotFound", type)); //$NON-NLS-1$
					}
				} else {
					logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.targetNotFound", id)); //$NON-NLS-1$
				}
			}
		}

		T search(IContentType type) {
			List<T> list = searchAll(type);
			return list != null ? list.get(0) : null;
		}

		List<T> searchAll(IContentType type) {
			if (fContentTypeBindings != null) {
				for (; type != null; type= type.getBaseType()) {
					List<T> data= fContentTypeBindings.get(type);
					if (data != null)
						return data;
				}
			}
			return null;
		}

		T search(String extension) {
			List<T> list = searchAll(extension);
			return list != null ? list.get(0) : null;
		}

		List<T> searchAll(String extension) {
			if (fExtensionMap != null)
				return fExtensionMap.get(normalizeCase(extension));
			return null;
		}
	}

	/** Status code describing an internal error */
	public static final int INTERNAL_ERROR= 1;

	private static boolean NORMALIZE_CASE= true;

	public static final String PLUGIN_ID= "org.eclipse.compare"; //$NON-NLS-1$

	private static final String BINARY_TYPE= "binary"; //$NON-NLS-1$

	private static final String STREAM_MERGER_EXTENSION_POINT= "streamMergers"; //$NON-NLS-1$
	private static final String STREAM_MERGER= "streamMerger"; //$NON-NLS-1$
	private static final String STREAM_MERGER_ID_ATTRIBUTE= "streamMergerId"; //$NON-NLS-1$
	private static final String STRUCTURE_CREATOR_EXTENSION_POINT= "structureCreators"; //$NON-NLS-1$
	private static final String STRUCTURE_CREATOR= "structureCreator"; //$NON-NLS-1$
	private static final String STRUCTURE_CREATOR_ID_ATTRIBUTE= "structureCreatorId"; //$NON-NLS-1$

	private static final String VIEWER_TAG= "viewer"; //$NON-NLS-1$
	private static final String FILTER_TAG = "filter"; //$NON-NLS-1$
	private static final String STRUCTURE_MERGE_VIEWER_EXTENSION_POINT= "structureMergeViewers"; //$NON-NLS-1$
	private static final String STRUCTURE_MERGE_VIEWER_ID_ATTRIBUTE= "structureMergeViewerId"; //$NON-NLS-1$
	private static final String CONTENT_MERGE_VIEWER_EXTENSION_POINT= "contentMergeViewers"; //$NON-NLS-1$
	private static final String COMPARE_FILTER_EXTENTION_POINT = "compareFilters"; //$NON-NLS-1$
	private static final String COMPARE_FILTER_ID_ATTRIBUTE = "filterId"; //$NON-NLS-1$
	private static final String CONTENT_MERGE_VIEWER_ID_ATTRIBUTE= "contentMergeViewerId"; //$NON-NLS-1$
	private static final String CONTENT_VIEWER_EXTENSION_POINT= "contentViewers"; //$NON-NLS-1$
	private static final String CONTENT_VIEWER_ID_ATTRIBUTE= "contentViewerId"; //$NON-NLS-1$

	private static final String CONTENT_TYPE_BINDING= "contentTypeBinding"; //$NON-NLS-1$


	private static final String COMPARE_EDITOR= PLUGIN_ID + ".CompareEditor"; //$NON-NLS-1$

	private static final String STRUCTUREVIEWER_ALIASES_PREFERENCE_NAME= "StructureViewerAliases";	//$NON-NLS-1$

	// content type
	private static final IContentTypeManager fgContentTypeManager= Platform.getContentTypeManager();

	public static final int NO_DIFFERENCE = 10000;

	/**
	 * The plugin singleton.
	 */
	private static CompareUIPlugin fgComparePlugin;

	/** Maps type to icons */
	private static Map<String, Image> fgImages= new Hashtable<>(10);
	/** Maps type to ImageDescriptors */
	private static Map<String, ImageDescriptor> fgImageDescriptors= new Hashtable<>(10);
	/** Maps ImageDescriptors to Images */
	private static Map<ImageDescriptor, Image> fgImages2= new Hashtable<>(10);

	private static List<Image> fgDisposeOnShutdownImages= new ArrayList<>();

	private ResourceBundle fResourceBundle;

	private boolean fRegistriesInitialized;
	private CompareRegistry<StreamMergerDescriptor> fStreamMergers= new CompareRegistry<>();
	private CompareRegistry<StructureCreatorDescriptor> fStructureCreators= new CompareRegistry<>();
	private CompareRegistry<ViewerDescriptor> fStructureMergeViewers= new CompareRegistry<>();
	private CompareRegistry<ViewerDescriptor> fContentViewers= new CompareRegistry<>();
	private CompareRegistry<ViewerDescriptor> fContentMergeViewers= new CompareRegistry<>();
	private CompareRegistry<CompareFilterDescriptor> fCompareFilters = new CompareRegistry<>();

	private Map<String, String> fStructureViewerAliases;
	private CompareResourceFilter fFilter;
	private IPropertyChangeListener fPropertyChangeListener;

	private ServiceRegistration<DebugOptionsListener> debugRegistration;

	/**
	 * Creates the <code>CompareUIPlugin</code> object and registers all
	 * structure creators, content merge viewers, and structure merge viewers
	 * contributed to this plug-in's extension points.
	 * <p>
	 * Note that instances of plug-in runtime classes are automatically created
	 * by the platform in the course of plug-in activation.
	 */
	public CompareUIPlugin() {
		super();
		Assert.isTrue(fgComparePlugin == null);
		fgComparePlugin= this;
	}

	@Override
	public void start(BundleContext context) throws Exception {
		super.start(context);

		Hashtable<String, String> properties = new Hashtable<>(2);
		properties.put(DebugOptions.LISTENER_SYMBOLICNAME, PLUGIN_ID);
		debugRegistration = context.registerService(DebugOptionsListener.class, Policy.DEBUG_OPTIONS_LISTENER,
				properties);

		ComparePlugin.getDefault().setCappingDisabled(
				getPreferenceStore().getBoolean(
						ComparePreferencePage.CAPPING_DISABLED));
	}

	@Override
	public void stop(BundleContext context) throws Exception {
		IPreferenceStore ps= getPreferenceStore();
		rememberAliases(ps);
		if (fPropertyChangeListener != null) {
			ps.removePropertyChangeListener(fPropertyChangeListener);
			fPropertyChangeListener= null;
		}

		super.stop(context);

		if (fgDisposeOnShutdownImages != null) {
			Iterator<Image> i= fgDisposeOnShutdownImages.iterator();
			while (i.hasNext()) {
				Image img= i.next();
				if (!img.isDisposed())
					img.dispose();
			}
			fgImages= null;
		}

		if (debugRegistration != null) {
			debugRegistration.unregister();
			debugRegistration = null;
		}
	}

	/**
	 * Returns the singleton instance of this plug-in runtime class.
	 *
	 * @return the compare plug-in instance
	 */
	public static CompareUIPlugin getDefault() {
		return fgComparePlugin;
	}

	/**
	 * Returns this plug-in's resource bundle.
	 *
	 * @return the plugin's resource bundle
	 */
	public ResourceBundle getResourceBundle() {
		if (fResourceBundle == null)
			fResourceBundle= Platform.getResourceBundle(getBundle());
		return fResourceBundle;
	}

	/**
	 * Returns this plug-in's unique identifier.
	 *
	 * @return the plugin's unique identifier
	 */
	public static String getPluginId() {
		return getDefault().getBundle().getSymbolicName();
	}

	private void initializeRegistries() {
		if (!fRegistriesInitialized) {
			registerExtensions();
			fRegistriesInitialized= true;
		}
	}

	/**
	 * Registers all stream mergers, structure creators, content merge viewers, and structure merge viewers
	 * that are found in the XML plugin files.
	 */
	private void registerExtensions() {
		IExtensionRegistry registry= Platform.getExtensionRegistry();

		// collect all IStreamMergers
		IConfigurationElement[] elements= registry.getConfigurationElementsFor(PLUGIN_ID, STREAM_MERGER_EXTENSION_POINT);
		for (IConfigurationElement element : elements) {
			if (STREAM_MERGER.equals(element.getName()))
				fStreamMergers.register(element, new StreamMergerDescriptor(element));
		}
		for (IConfigurationElement element : elements) {
			if (CONTENT_TYPE_BINDING.equals(element.getName()))
				fStreamMergers.createBinding(element, STREAM_MERGER_ID_ATTRIBUTE);
		}

		// collect all IStructureCreators
		elements= registry.getConfigurationElementsFor(PLUGIN_ID, STRUCTURE_CREATOR_EXTENSION_POINT);
		for (IConfigurationElement element : elements) {
			String name= element.getName();
			if (!CONTENT_TYPE_BINDING.equals(name)) {
				if (!STRUCTURE_CREATOR.equals(name))
					logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.unexpectedTag", name, STRUCTURE_CREATOR)); //$NON-NLS-1$
				fStructureCreators.register(element, new StructureCreatorDescriptor(element));
			}
		}
		for (IConfigurationElement element : elements) {
			if (CONTENT_TYPE_BINDING.equals(element.getName()))
				fStructureCreators.createBinding(element, STRUCTURE_CREATOR_ID_ATTRIBUTE);
		}

		// collect all viewers which define the structure merge viewer extension point
		elements= registry.getConfigurationElementsFor(PLUGIN_ID, STRUCTURE_MERGE_VIEWER_EXTENSION_POINT);
		for (IConfigurationElement element : elements) {
			String name= element.getName();
			if (!CONTENT_TYPE_BINDING.equals(name)) {
				if (!VIEWER_TAG.equals(name))
					logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); //$NON-NLS-1$
				fStructureMergeViewers.register(element, new ViewerDescriptor(element));
			}
		}
		for (IConfigurationElement element : elements) {
			if (CONTENT_TYPE_BINDING.equals(element.getName()))
				fStructureMergeViewers.createBinding(element, STRUCTURE_MERGE_VIEWER_ID_ATTRIBUTE);
		}

		// collect all viewers which define the content merge viewer extension point
		elements= registry.getConfigurationElementsFor(PLUGIN_ID, CONTENT_MERGE_VIEWER_EXTENSION_POINT);
		for (IConfigurationElement element : elements) {
			String name= element.getName();
			if (!CONTENT_TYPE_BINDING.equals(name)) {
				if (!VIEWER_TAG.equals(name))
					logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); //$NON-NLS-1$
				fContentMergeViewers.register(element, new ViewerDescriptor(element));
			}
		}
		for (IConfigurationElement element : elements) {
			if (CONTENT_TYPE_BINDING.equals(element.getName()))
				fContentMergeViewers.createBinding(element, CONTENT_MERGE_VIEWER_ID_ATTRIBUTE);
		}

		// collect all extensions that define the compare filter extension point
		elements = registry.getConfigurationElementsFor(PLUGIN_ID,
				COMPARE_FILTER_EXTENTION_POINT);
		for (IConfigurationElement element : elements) {
			String name = element.getName();
			if (!CONTENT_TYPE_BINDING.equals(name)) {
				if (!FILTER_TAG.equals(name))
					logErrorMessage(Utilities.getFormattedString(
							"CompareUIPlugin.unexpectedTag", name, FILTER_TAG)); //$NON-NLS-1$
				fCompareFilters.register(element, new CompareFilterDescriptor(element));
			}
		}
		for (IConfigurationElement element : elements) {
			if (CONTENT_TYPE_BINDING.equals(element.getName()))
				fCompareFilters.createBinding(element,
						COMPARE_FILTER_ID_ATTRIBUTE);
		}

		// collect all viewers which define the content viewer extension point
		elements= registry.getConfigurationElementsFor(PLUGIN_ID, CONTENT_VIEWER_EXTENSION_POINT);
		for (IConfigurationElement element : elements) {
			String name= element.getName();
			if (!CONTENT_TYPE_BINDING.equals(name)) {
				if (!VIEWER_TAG.equals(name))
					logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); //$NON-NLS-1$
				fContentViewers.register(element, new ViewerDescriptor(element));
			}
		}
		for (IConfigurationElement element : elements) {
			if (CONTENT_TYPE_BINDING.equals(element.getName()))
				fContentViewers.createBinding(element, CONTENT_VIEWER_ID_ATTRIBUTE);
		}
	}

	public static IWorkbench getActiveWorkbench() {
		return PlatformUI.getWorkbench();
	}

	public static IWorkbenchWindow getActiveWorkbenchWindow() {
		IWorkbench workbench= getActiveWorkbench();
		if (workbench == null)
			return null;
		return workbench.getActiveWorkbenchWindow();
	}

	/**
	 * Returns the active workbench page or <code>null</code> if
	 * no active workbench page can be determined.
	 *
	 * @return the active workbench page or <code>null</code> if
	 * 	no active workbench page can be determined
	 */
	private static IWorkbenchPage getActivePage() {
		IWorkbenchWindow window= getActiveWorkbenchWindow();
		if (window == null)
			return null;
		return window.getActivePage();
	}

	/**
	 * If the workbench is running returns the SWT Shell of the active workbench window or <code>null</code> if
	 * no workbench window is active.
	 *
	 * If the workbench is not running, returns the shell of the default display.
	 *
	 * @return If the workbench is running, returns the SWT Shell of the active workbench window, or <code>null</code> if
	 * 	no workbench window is active. Otherwise returns the shell of the default display.
	 */
	public static Shell getShell() {
		if(PlatformUI.isWorkbenchRunning()){
			IWorkbenchWindow window = getActiveWorkbenchWindow();
			if (window == null)
				return null;
			return window.getShell();
		}

		return Display.getDefault().getActiveShell();
	}

	/**
	 * Registers the given image for being disposed when this plug-in is shutdown.
	 *
	 * @param image the image to register for disposal
	 */
	public static void disposeOnShutdown(Image image) {
		if (image != null)
			fgDisposeOnShutdownImages.add(image);
	}

	/**
	 * Performs the comparison described by the given input and opens a compare
	 * editor on the result.
	 *
	 * @param input
	 *            the input on which to open the compare editor
	 * @param page
	 *            the workbench page on which to create a new compare editor
	 * @param editor
	 *            if not null the input is opened in this editor
	 * @param activate
	 *            if <code>true</code> the editor will be activated
	 * @see IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput, String,
	 *      boolean)
	 * @see CompareEditorInput
	 */
	public void openCompareEditor(final CompareEditorInput input,
			final IWorkbenchPage page, final IReusableEditor editor,
			final boolean activate) {
		CompareConfiguration configuration = input.getCompareConfiguration();
		if (configuration != null) {
			IPreferenceStore ps= configuration.getPreferenceStore();
			if (ps != null)
				configuration.setProperty(
						CompareConfiguration.USE_OUTLINE_VIEW,
						Boolean.valueOf(ps.getBoolean(ComparePreferencePage.USE_OUTLINE_VIEW)));
		}
		if (input.canRunAsJob()) {
			openEditorInBackground(input, page, editor, activate);
		} else {
			if (compareResultOK(input, null)) {
				internalOpenEditor(input, page, editor, activate);
			}
		}
	}

	private void openEditorInBackground(final CompareEditorInput input,
			final IWorkbenchPage page, final IReusableEditor editor,
			final boolean activate) {
		internalOpenEditor(input, page, editor, activate);
	}

	private void internalOpenEditor(final CompareEditorInput input,
			final IWorkbenchPage wp, final IReusableEditor editor,
			final boolean activate) {
		Runnable runnable = () -> {
			if (editor != null && !editor.getSite().getShell().isDisposed()) {	// reuse the given editor
				editor.setInput(input);
				return;
			}

			IWorkbenchPage page = wp;
			if (page == null)
				page= getActivePage();
			if (page != null) {
				// open new CompareEditor on page
				try {
					page.openEditor(input, COMPARE_EDITOR, activate);
				} catch (PartInitException e) {
					MessageDialog.openError(getShell(), Utilities.getString("CompareUIPlugin.openEditorError"), e.getMessage()); //$NON-NLS-1$
				}
			} else {
				MessageDialog.openError(getShell(),
						Utilities.getString("CompareUIPlugin.openEditorError"), //$NON-NLS-1$
						Utilities.getString("CompareUIPlugin.noActiveWorkbenchPage")); //$NON-NLS-1$
			}
		};
		syncExec(runnable);
	}

	/**
	 * Performs the comparison described by the given input and opens a
	 * compare dialog on the result.
	 *
	 * @param input the input on which to open the compare editor
	 * @see CompareEditorInput
	 */
	public void openCompareDialog(final CompareEditorInput input) {
		// We don't ever open dialogs in the background
		if (compareResultOK(input, null)) {
			internalOpenDialog(input);
		}
	}

	public IStatus prepareInput(CompareEditorInput input, IProgressMonitor monitor) {
		try {
			input.run(monitor);
			String message= input.getMessage();
			if (message != null) {
				return new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, message, null);
			}
			if (input.getCompareResult() == null) {
				return new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, NO_DIFFERENCE, Utilities.getString("CompareUIPlugin.noDifferences"), null); //$NON-NLS-1$
			}
			return Status.OK_STATUS;
		} catch (InterruptedException e) {
			throw new OperationCanceledException();
		} catch (InvocationTargetException e) {
			return new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, Utilities.getString("CompareUIPlugin.compareFailed"), e.getTargetException()); //$NON-NLS-1$
		}
	}

	/*
	 * @return <code>true</code> if compare result is OK to show, <code>false</code> otherwise
	 */
	public boolean compareResultOK(CompareEditorInput input, IRunnableContext context) {
		final Shell shell= getShell();
		try {
			// run operation in context if possible
			if (context != null) {
				context.run(true, true, input);
			} else {
				Utilities.executeRunnable(input);
			}

			String message= input.getMessage();
			if (message != null) {
				MessageDialog.openError(shell, Utilities.getString("CompareUIPlugin.compareFailed"), message); //$NON-NLS-1$
				return false;
			}

			if (input.getCompareResult() == null) {
				MessageDialog.openInformation(shell, Utilities.getString("CompareUIPlugin.dialogTitle"), Utilities.getString("CompareUIPlugin.noDifferences")); //$NON-NLS-2$ //$NON-NLS-1$
				return false;
			}

			return true;
		} catch (InterruptedException x) {
			// canceled by user
		} catch (InvocationTargetException x) {
			MessageDialog.openError(shell, Utilities.getString("CompareUIPlugin.compareFailed"), x.getTargetException().getMessage()); //$NON-NLS-1$
		}
		return false;
	}

	/*
	 * Registers an image for the given type.
	 */
	private static void registerImage(String type, Image image, boolean dispose) {
		fgImages.put(normalizeCase(type), image);
		if (image != null && dispose) {
			fgDisposeOnShutdownImages.add(image);
		}
	}

	/**
	 * Registers an image descriptor for the given type.
	 *
	 * @param type the type
	 * @param descriptor the image descriptor
	 */
	public static void registerImageDescriptor(String type, ImageDescriptor descriptor) {
		fgImageDescriptors.put(normalizeCase(type), descriptor);
	}

	public static ImageDescriptor getImageDescriptor(String relativePath) {
		if (fgComparePlugin == null)
			return null;
		IPath path= Utilities.getIconPath(null).append(relativePath);
		URL url= FileLocator.find(fgComparePlugin.getBundle(), path, null);
		if (url == null)
			return null;
		return ImageDescriptor.createFromURL(url);
	}

	/**
	 * Returns a shared image for the given type, or a generic image if none
	 * has been registered for the given type.
	 * <p>
	 * Note: Images returned from this method will be automatically disposed
	 * of when this plug-in shuts down. Callers must not dispose of these
	 * images themselves.
	 * </p>
	 *
	 * @param type the type
	 * @return the image
	 */
	public static Image getImage(String type) {

		type= normalizeCase(type);

		boolean dispose= false;
		Image image= null;
		if (type != null)
			image= fgImages.get(type);
		if (image == null) {
			ImageDescriptor id= fgImageDescriptors.get(type);
			if (id != null) {
				image= id.createImage();
				dispose= true;
			}

			if (image == null) {
				if (fgComparePlugin != null) {
					if (ITypedElement.FOLDER_TYPE.equals(type)) {
						image = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
						//image= SharedImages.getImage(ISharedImages.IMG_OBJ_FOLDER);
					} else {
						image= createWorkbenchImage(type);
						dispose= true;
					}
				} else {
					id= fgImageDescriptors.get(normalizeCase("file")); //$NON-NLS-1$
					image= id.createImage();
					dispose= true;
				}
			}
			if (image != null)
				registerImage(type, image, dispose);
		}
		return image;
	}

	/**
	 * Returns a shared image for the given adaptable.
	 * This convenience method queries the given adaptable
	 * for its <code>IWorkbenchAdapter.getImageDescriptor</code>, which it
	 * uses to create an image if it does not already have one.
	 * <p>
	 * Note: Images returned from this method will be automatically disposed
	 * of when this plug-in shuts down. Callers must not dispose of these
	 * images themselves.
	 * </p>
	 *
	 * @param adaptable the adaptable for which to find an image
	 * @return an image
	 */
	public static Image getImage(IAdaptable adaptable) {
		if (adaptable != null) {
			IWorkbenchAdapter o= Adapters.adapt(adaptable, IWorkbenchAdapter.class);
			ImageDescriptor id= o.getImageDescriptor(adaptable);
			if (id != null) {
				Image image= fgImages2.get(id);
				if (image == null) {
					image= id.createImage();
					try {
						fgImages2.put(id, image);
					} catch (NullPointerException e) {
						// NeedWork
					}
					fgDisposeOnShutdownImages.add(image);

				}
				return image;
			}
		}
		return null;
	}

	private static Image createWorkbenchImage(String type) {
		IEditorRegistry er= PlatformUI.getWorkbench().getEditorRegistry();
		ImageDescriptor id= er.getImageDescriptor("foo." + type); //$NON-NLS-1$
		return id.createImage();
	}

	/**
	 * Returns an structure creator descriptor for the given type.
	 *
	 * @param type the type for which to find a descriptor
	 * @return a descriptor for the given type, or <code>null</code> if no
	 *   descriptor has been registered
	 */
	public StructureCreatorDescriptor getStructureCreator(String type) {
		initializeRegistries();
		return fStructureCreators.search(type);
	}

	/**
	 * Returns a stream merger for the given type.
	 *
	 * @param type the type for which to find a stream merger
	 * @return a stream merger for the given type, or <code>null</code> if no
	 *   stream merger has been registered
	 */
	public IStreamMerger createStreamMerger(String type) {
		initializeRegistries();
		StreamMergerDescriptor descriptor= fStreamMergers.search(type);
		if (descriptor != null)
			return descriptor.createStreamMerger();
		return null;
	}

	/**
	 * Returns a stream merger for the given content type.
	 *
	 * @param type the type for which to find a stream merger
	 * @return a stream merger for the given type, or <code>null</code> if no
	 *   stream merger has been registered
	 */
	public IStreamMerger createStreamMerger(IContentType type) {
		initializeRegistries();
		StreamMergerDescriptor descriptor= fStreamMergers.search(type);
		if (descriptor != null)
			return descriptor.createStreamMerger();
		return null;
	}

	public ViewerDescriptor[] findStructureViewerDescriptor(Viewer oldViewer,
			ICompareInput input, CompareConfiguration configuration) {
		if (input == null)
			return null;
		// we don't show the structure of additions or deletions
		if (input == null || input.getLeft() == null || input.getRight() == null)
			return null;

		Set<ViewerDescriptor> result = new LinkedHashSet<>();

		// content type search
		IContentType ctype= getCommonType(input);
		if (ctype != null) {
			initializeRegistries();
			List<ViewerDescriptor> list = fStructureMergeViewers.searchAll(ctype);
			if (list != null)
				result.addAll(list);
		}

		// old style search
		String[] types= getTypes(input);
		String type= null;
		if (isHomogenous(types)) {
			type= normalizeCase(types[0]);
			initializeRegistries();
			List<ViewerDescriptor> list = fStructureMergeViewers.searchAll(type);
			if (list != null)
				result.addAll(list);
			String alias= getStructureViewerAlias(type);
			if (alias != null) {
				list = fStructureMergeViewers.searchAll(alias);
				if (list != null)
					result.addAll(list);
			}
		}

		return result.size() > 0 ? result.toArray(new ViewerDescriptor[0]) : null;
	}

	/**
	 * Returns a structure compare viewer based on an old viewer and an input object.
	 * If the old viewer is suitable for showing the input, the old viewer
	 * is returned. Otherwise, the input's type is used to find a viewer descriptor in the registry
	 * which in turn is used to create a structure compare viewer under the given parent composite.
	 * If no viewer descriptor can be found <code>null</code> is returned.
	 *
	 * @param oldViewer a new viewer is only created if this old viewer cannot show the given input
	 * @param input the input object for which to find a structure viewer
	 * @param parent the SWT parent composite under which the new viewer is created
	 * @param configuration a configuration which is passed to a newly created viewer
	 * @return the compare viewer which is suitable for the given input object or <code>null</code>
	 */
	public Viewer findStructureViewer(Viewer oldViewer, ICompareInput input, Composite parent,
				CompareConfiguration configuration) {
		ViewerDescriptor[] descriptors = findStructureViewerDescriptor(oldViewer, input, configuration);
		if (descriptors == null || descriptors.length == 0) {
			// we didn't found any viewer so far.
			// now we try to find a structure creator for the generic StructureDiffViewer
			IContentType ctype= getCommonType(input);

			String[] types= getTypes(input);
			String type= null;
			if (isHomogenous(types)) {
				type= normalizeCase(types[0]);
			}

			initializeRegistries();
			StructureCreatorDescriptor scc= fStructureCreators.search(ctype);	// search for content type
			if (scc == null && type != null)
				scc= getStructureCreator(type);	// search for old-style type scheme
			if (scc != null) {
				IStructureCreator sc= scc.createStructureCreator();
				if (sc != null) {
					StructureDiffViewer sdv= new StructureDiffViewer(parent, configuration);
					sdv.setStructureCreator(sc);
					return sdv;
				}
			}
			return null;
		}
		return getViewer(descriptors[0], oldViewer, parent, configuration);
	}

	public CompareFilterDescriptor[] findCompareFilters(Object in) {
		Collection<Object> contentTypes = getContentTypes(in);
		if (contentTypes == null) {
			return new CompareFilterDescriptor[0];
		}
		Set<CompareFilterDescriptor> result = new LinkedHashSet<>();
		Iterator<Object> ctIterator = contentTypes.iterator();
		while (ctIterator.hasNext()) {
			Object ct = ctIterator.next();
			if (ct instanceof IContentType) {
				List<CompareFilterDescriptor> list = fCompareFilters.searchAll((IContentType) ct);
				if (list != null)
					result.addAll(list);
			} else if (ct instanceof String) {
				List<CompareFilterDescriptor> list = fCompareFilters.searchAll((String) ct);
				if (list != null)
					result.addAll(list);
			}
		}

		ArrayList<CompareFilterDescriptor> list = new ArrayList<>(result);
		Collections.sort(list, (left, right) -> left.getFilterId().compareTo(right.getFilterId()));

		return result.toArray(new CompareFilterDescriptor[result.size()]);
	}

	private Collection<Object> getContentTypes(Object in) {
		Set<Object> result = new LinkedHashSet<>();
		if (in instanceof IStreamContentAccessor) {
			String type = ITypedElement.TEXT_TYPE;

			if (in instanceof ITypedElement) {
				ITypedElement tin = (ITypedElement) in;

				IContentType ct = getContentType(tin);
				if (ct != null) {
					result.add(ct);
				}

				String ty = tin.getType();
				if (ty != null)
					type = ty;
				result.add(type);
			}
			return result;
		}

		if (!(in instanceof ICompareInput))
			return null;

		ICompareInput input = (ICompareInput) in;

		IContentType ctype = getCommonType(input);
		if (ctype != null) {
			result.add(ctype);
		}

		String[] types = getTypes(input);
		String type = null;
		if (isHomogenous(types))
			type = types[0];

		if (ITypedElement.FOLDER_TYPE.equals(type))
			return null;

		if (type == null) {
			int n = 0;
			for (String t : types) {
				if (!ITypedElement.UNKNOWN_TYPE.equals(t)) {
					n++;
					if (type == null) {
						type = t; // remember the first known type
					}
				}
			}
			if (n > 1) // don't use the type if there were more than one
				type = null;
		}

		if (type != null) {
			result.add(type);
		}

		// fallback
		String leftType = guessType(input.getLeft());
		String rightType = guessType(input.getRight());

		if (leftType != null || rightType != null) {
			boolean right_text = rightType != null
					&& ITypedElement.TEXT_TYPE.equals(rightType);
			boolean left_text = leftType != null
					&& ITypedElement.TEXT_TYPE.equals(leftType);
			if ((rightType != null && !right_text)
					|| (leftType != null && !left_text)) {
				result.add(BINARY_TYPE);
			}
			result.add(ITypedElement.TEXT_TYPE);
		}
		return result;
	}

	public ViewerDescriptor[] findContentViewerDescriptor(Viewer oldViewer, Object in, CompareConfiguration cc) {
		Set<ViewerDescriptor> result = new LinkedHashSet<>();
		if (in instanceof IStreamContentAccessor) {
			String type= ITypedElement.TEXT_TYPE;

			if (in instanceof ITypedElement) {
				ITypedElement tin= (ITypedElement) in;

				IContentType ct= getContentType(tin);
				if (ct != null) {
					initializeRegistries();
					List<ViewerDescriptor> list = fContentViewers.searchAll(ct);
					if (list != null)
						result.addAll(list);
				}

				String ty= tin.getType();
				if (ty != null)
					type= ty;
			}

			initializeRegistries();
			List<ViewerDescriptor> list = fContentViewers.searchAll(type);
			if (list != null)
				result.addAll(list);
			// fallback
			result.add(fContentViewers.search(Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT)));
			return result.toArray(new ViewerDescriptor[0]);
		}

		if (!(in instanceof ICompareInput))
			return null;

		ICompareInput input= (ICompareInput) in;

		IContentType ctype = getCommonType(input);
		if (ctype != null) {
			initializeRegistries();
			List<ViewerDescriptor> list = fContentMergeViewers.searchAll(ctype);
			if (list != null)
				result.addAll(list);
		}

		String[] types= getTypes(input);
		String type= null;
		if (isHomogenous(types))
			type= types[0];

		if (ITypedElement.FOLDER_TYPE.equals(type))
			return null;

		if (type == null) {
			int n= 0;
			for (String t : types) {
				if (!ITypedElement.UNKNOWN_TYPE.equals(t)) {
					n++;
					if (type == null) {
						type = t; // remember the first known type
					}
				}
			}
			if (n > 1)	// don't use the type if there were more than one
				type= null;
		}

		if (type != null) {
			initializeRegistries();
			List<ViewerDescriptor> list = fContentMergeViewers.searchAll(type);
			if (list != null)
				result.addAll(list);
		}

		// fallback
		String leftType= guessType(input.getLeft());
		String rightType= guessType(input.getRight());

		if (leftType != null || rightType != null) {
			boolean right_text = rightType != null
					&& ITypedElement.TEXT_TYPE.equals(rightType);
			boolean left_text = leftType != null
					&& ITypedElement.TEXT_TYPE.equals(leftType);
			initializeRegistries();
			if ((rightType != null && !right_text)
					|| (leftType != null && !left_text)) {
				List<ViewerDescriptor> list = fContentMergeViewers.searchAll(BINARY_TYPE);
				if (list != null)
					result.addAll(list);
			}
			List<ViewerDescriptor> list = fContentMergeViewers.searchAll(ITypedElement.TEXT_TYPE);
			if (list != null)
				result.addAll(list);

			return result.toArray(new ViewerDescriptor[0]);
		}
		return result.isEmpty() ? null : result.toArray(new ViewerDescriptor[0]);
	}

	/**
	 * Returns a content compare viewer based on an old viewer and an input object.
	 * If the old viewer is suitable for showing the input the old viewer
	 * is returned. Otherwise the input's type is used to find a viewer descriptor in the registry
	 * which in turn is used to create a content compare viewer under the given parent composite.
	 * If no viewer descriptor can be found <code>null</code> is returned.
	 *
	 * @param oldViewer a new viewer is only created if this old viewer cannot show the given input
	 * @param in the input object for which to find a content viewer
	 * @param parent the SWT parent composite under which the new viewer is created
	 * @param cc a configuration which is passed to a newly created viewer
	 * @return the compare viewer which is suitable for the given input object or <code>null</code>
	 */
	public Viewer findContentViewer(Viewer oldViewer, Object in,
			Composite parent, CompareConfiguration cc) {
		ViewerDescriptor[] descriptors = findContentViewerDescriptor(oldViewer, in, cc);
		return getViewer(descriptors != null ? descriptors[0] : null, oldViewer, parent, cc);
	}

	private static Viewer getViewer(Object descriptor, Viewer oldViewer, Composite parent, CompareConfiguration cc) {
		if (descriptor instanceof IViewerDescriptor)
			return ((IViewerDescriptor)descriptor).createViewer(oldViewer, parent, cc);
		return null;
	}

	private static String[] getTypes(ICompareInput input) {
		ITypedElement ancestor= input.getAncestor();
		ITypedElement left= input.getLeft();
		ITypedElement right= input.getRight();

		ArrayList<String> tmp= new ArrayList<>();
		if (ancestor != null) {
			String type= ancestor.getType();
			if (type != null)
				tmp.add(normalizeCase(type));
		}
		if (left != null) {
			String type= left.getType();
			if (type != null)
				tmp.add(normalizeCase(type));
		}
		if (right != null) {
			String type= right.getType();
			if (type != null)
				tmp.add(normalizeCase(type));
		}
		return tmp.toArray(new String[tmp.size()]);
	}

	private static IContentType getContentType(ITypedElement element) {
		if (element == null)
			return null;
		String name= element.getName();
		IContentType ct= null;
		if (element instanceof IResourceProvider) {
			IResource resource= ((IResourceProvider)element).getResource();
			if (resource instanceof IFile) {
				try {
					IContentDescription contentDesc= ((IFile)resource).getContentDescription();
					return contentDesc != null ? contentDesc.getContentType() : null;
				} catch (CoreException e) {
					//$FALL-THROUGH$
				}
			}
		}
		if (element instanceof IStreamContentAccessor) {
			IStreamContentAccessor isa= (IStreamContentAccessor) element;
			try {
				InputStream is= isa.getContents();
				if (is != null) {
					InputStream bis= new BufferedInputStream(is);
					try {
						ct= fgContentTypeManager.findContentTypeFor(is, name);
					} catch (IOException e) {
						// silently ignored
					} finally {
						try {
							bis.close();
						} catch (IOException e2) {
							// silently ignored
						}
					}
				}
			} catch (CoreException e1) {
				// silently ignored
			}
		}
		if (ct == null)
			ct= fgContentTypeManager.findContentTypeFor(name);
		return ct;
	}

	/*
	 * Returns true if the given types are homogeneous.
	 */
	private static boolean isHomogenous(String[] types) {
		switch (types.length) {
		case 1:
			return true;
		case 2:
			return types[0].equals(types[1]);
		case 3:
			return types[0].equals(types[1]) && types[1].equals(types[2]);
		}
		return false;
	}

	/*
	 * Returns the most specific content type that is common to the given inputs or null.
	 */
	private static IContentType getCommonType(ICompareInput input) {
		ITypedElement ancestor= input.getAncestor();
		ITypedElement left= input.getLeft();
		ITypedElement right= input.getRight();

		int n= 0;
		IContentType[] types= new IContentType[3];
		IContentType type= null;

		if (ancestor != null) {
			type= getContentType(ancestor);
			if (type != null)
				types[n++]= type;
		}
		type= getContentType(left);
		if (type != null)
			types[n++]= type;
		type= getContentType(right);
		if (type != null)
			types[n++]= type;

		IContentType result= null;
		IContentType[] s0, s1, s2;
		switch (n) {
		case 0:
			return null;
		case 1:
			return types[0];
		case 2:
			if (types[0].equals(types[1]))
				return types[0];
			s0= toFullPath(types[0]);
			s1= toFullPath(types[1]);
			for (int i= 0; i < Math.min(s0.length, s1.length); i++) {
				if (!s0[i].equals(s1[i]))
					break;
				result= s0[i];
			}
			return result;
		case 3:
			if (types[0].equals(types[1]) && types[1].equals(types[2]))
				return types[0];
			s0= toFullPath(types[0]);
			s1= toFullPath(types[1]);
			s2= toFullPath(types[2]);
			for (int i= 0; i < Math.min(Math.min(s0.length, s1.length), s2.length); i++) {
				if (!s0[i].equals(s1[i]) || !s1[i].equals(s2[i]))
					break;
				result= s0[i];
			}
			return result;
		}
		return null;
	}

	private static IContentType[] toFullPath(IContentType ct) {
		List<IContentType> l= new ArrayList<>();
		for (; ct != null; ct= ct.getBaseType())
			l.add(0, ct);
		return l.toArray(new IContentType[l.size()]);
	}

	/*
	 * Guesses the file type of the given input.
	 * Returns ITypedElement.TEXT_TYPE if none of the first 10 lines is longer than 1000 bytes.
	 * Returns ITypedElement.UNKNOWN_TYPE otherwise.
	 * Returns <code>null</code> if the input isn't an <code>IStreamContentAccessor</code>.
	 */
	private static String guessType(ITypedElement input) {
		if (input instanceof IStreamContentAccessor) {
			IStreamContentAccessor sca= (IStreamContentAccessor) input;
			InputStream is= null;
			try {
				is= sca.getContents();
				if (is == null)
					return null;
				int lineLength= 0;
				int lines= 0;
				while (lines < 10) {
					int c= is.read();
					if (c == -1)	// EOF
						break;
					if (c == '\n' || c == '\r') { // reset line length
						lineLength= 0;
						lines++;
					} else
						lineLength++;
					if (lineLength > 1000)
						return ITypedElement.UNKNOWN_TYPE;
				}
				return ITypedElement.TEXT_TYPE;
			} catch (CoreException | IOException ex) {
				// be silent and return UNKNOWN_TYPE
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException ex) {
						// silently ignored
					}
				}
			}
			return ITypedElement.UNKNOWN_TYPE;
		}
		return null;
	}

	private static String normalizeCase(String s) {
		if (NORMALIZE_CASE && s != null)
			return s.toUpperCase();
		return s;
	}

	//---- alias management

	private String getStructureViewerAlias(String type) {
		return getStructureViewerAliases().get(type);
	}

	public void addStructureViewerAlias(String type, String alias) {
		getStructureViewerAliases().put(normalizeCase(alias), normalizeCase(type));
	}

	private Map<String, String> getStructureViewerAliases() {
		if (fStructureViewerAliases == null) {
			fStructureViewerAliases= new Hashtable<>(10);
			String aliases= getPreferenceStore().getString(STRUCTUREVIEWER_ALIASES_PREFERENCE_NAME);
			if (aliases != null && aliases.length() > 0) {
				StringTokenizer st= new StringTokenizer(aliases, " ");	//$NON-NLS-1$
				while (st.hasMoreTokens()) {
					String pair= st.nextToken();
					int pos= pair.indexOf('.');
					if (pos > 0) {
						String key= pair.substring(0, pos);
						String alias= pair.substring(pos+1);
						fStructureViewerAliases.put(key, alias);
					}
				}
			}
		}
		return fStructureViewerAliases;
	}

	public void removeAllStructureViewerAliases(String type) {
		if (fStructureViewerAliases == null)
			return;
		String t= normalizeCase(type);
		Set<Entry<String, String>> entrySet= fStructureViewerAliases.entrySet();
		for (Iterator<Map.Entry<String, String>> iter= entrySet.iterator(); iter.hasNext(); ) {
			Map.Entry<String, String> entry= iter.next();
			if (entry.getValue().equals(t))
				iter.remove();
		}
	}

	/*
	 * Converts the aliases into a single string before they are stored
	 * in the preference store.
	 * The format is:
	 * <key> '.' <alias> ' ' <key> '.' <alias> ...
	 */
	private void rememberAliases(IPreferenceStore ps) {
		if (fStructureViewerAliases == null)
			return;
		StringBuilder buffer= new StringBuilder();
		for (Map.Entry<String, String> entry : fStructureViewerAliases.entrySet()) {
			String key= entry.getKey();
			String alias= entry.getValue();
			buffer.append(key);
			buffer.append('.');
			buffer.append(alias);
			buffer.append(' ');
		}
		ps.setValue(STRUCTUREVIEWER_ALIASES_PREFERENCE_NAME, buffer.toString());
	}

	//---- filters

	public boolean filter(String name, boolean isFolder, boolean isArchive) {
		if (fFilter == null) {
			fFilter= new CompareResourceFilter();
			final IPreferenceStore ps= getPreferenceStore();
			fFilter.setFilters(ps.getString(ComparePreferencePage.PATH_FILTER));
			fPropertyChangeListener= event -> {
				if (ComparePreferencePage.PATH_FILTER.equals(event.getProperty()))
					fFilter.setFilters(ps.getString(ComparePreferencePage.PATH_FILTER));
			};
			ps.addPropertyChangeListener(fPropertyChangeListener);
		}
		return fFilter.filter(name, isFolder, isArchive);
	}

	private void internalOpenDialog(final CompareEditorInput input) {
		syncExec(() -> {
			Shell shell;
			if (PlatformUI.isWorkbenchRunning()) {
				shell = PlatformUI.getWorkbench().getModalDialogShellProvider().getShell();
			} else {
				shell = Display.getDefault().getActiveShell();
			}
			CompareDialog dialog = new CompareDialog(shell, input);
			dialog.open();
		});
	}

	private void syncExec(Runnable runnable) {
		if (Display.getCurrent() == null) {
			Display.getDefault().syncExec(runnable);
		} else {
			runnable.run();
		}
	}

	//---- more utilities

	protected void handleNoDifference() {
		Runnable runnable = () -> MessageDialog.openInformation(getShell(), Utilities.getString("CompareUIPlugin.dialogTitle"), Utilities.getString("CompareUIPlugin.noDifferences"));
		syncExec(runnable);
	}

	/**
	 * Returns an array of all editors that have an unsaved content. If the identical content is
	 * presented in more than one editor, only one of those editor parts is part of the result.
	 *
	 * @return an array of all dirty editor parts.
	 */
	public static IEditorPart[] getDirtyEditors() {
		Set<IEditorInput> inputs= new HashSet<>();
		List<IEditorPart> result= new ArrayList<>(0);
		IWorkbench workbench = PlatformUI.getWorkbench();
		IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
		for (IWorkbenchWindow window : windows) {
			IWorkbenchPage[] pages = window.getPages();
			for (IWorkbenchPage page : pages) {
				IEditorPart[] editors = page.getDirtyEditors();
				for (IEditorPart ep : editors) {
					IEditorInput input= ep.getEditorInput();
					if (!inputs.contains(input)) {
						inputs.add(input);
						result.add(ep);
					}
				}
			}
		}
		return result.toArray(new IEditorPart[result.size()]);
	}

	public static void logErrorMessage(String message) {
		if (message == null)
			message= ""; //$NON-NLS-1$
		log(new Status(IStatus.ERROR, getPluginId(), INTERNAL_ERROR, message, null));
	}

	public static void log(Throwable e) {
		log(new Status(IStatus.ERROR, getPluginId(), INTERNAL_ERROR, CompareMessages.ComparePlugin_internal_error, e));
	}

	public static void log(IStatus status) {
		getDefault().getLog().log(status);
	}

	String findContentTypeNameOrType(ICompareInput input, ViewerDescriptor vd, CompareConfiguration cc) {
		IContentType ctype= getCommonType(input);
		if (ctype != null) {
			initializeRegistries();
			List<ViewerDescriptor> list = fContentMergeViewers.searchAll(ctype);
			if (list != null)
				if (list.contains(vd))
					return ctype.getName();
		}

		String[] types= getTypes(input);
		String type= null;
		if (isHomogenous(types))
			type= types[0];

		if (ITypedElement.FOLDER_TYPE.equals(type))
			return null;

		if (type == null) {
			int n= 0;
			for (String t : types) {
				if (!ITypedElement.UNKNOWN_TYPE.equals(t)) {
					n++;
					if (type == null) {
						type = t; // remember the first known type
					}
				}
			}
			if (n > 1)	// don't use the type if there were more than one
				type= null;
		}

		if (type != null) {
			initializeRegistries();
			List<ViewerDescriptor> list = fContentMergeViewers.searchAll(type);
			if (list != null)
				if (list.contains(vd))
					return type;
		}

		// fallback
		String leftType= guessType(input.getLeft());
		String rightType= guessType(input.getRight());

		if (leftType != null || rightType != null) {
			boolean right_text = rightType != null
					&& ITypedElement.TEXT_TYPE.equals(rightType);
			boolean left_text = leftType != null
					&& ITypedElement.TEXT_TYPE.equals(leftType);
			initializeRegistries();
			if ((rightType != null && !right_text)
					|| (leftType != null && !left_text)) {
				List<ViewerDescriptor> list = fContentMergeViewers.searchAll(BINARY_TYPE);
				if (list != null)
					if (list.contains(vd))
						return type;
			}
			List<ViewerDescriptor> list = fContentMergeViewers.searchAll(ITypedElement.TEXT_TYPE);
			if (list != null)
				if (list.contains(vd))
					return type;
		}
		return null;
	}

	String findStructureTypeNameOrType(ICompareInput input, ViewerDescriptor vd, CompareConfiguration cc) {
		if (input == null)
			return null;
		// We don't show the structure of additions or deletions
		if (input == null || input.getLeft() == null || input.getRight() == null)
			return null;

		// Content type search
		IContentType ctype= getCommonType(input);
		if (ctype != null) {
			initializeRegistries();
			List<ViewerDescriptor> list = fStructureMergeViewers.searchAll(ctype);
			if (list != null)
				if (list.contains(vd))
					return ctype.getName();
		}

		// Old style search
		String[] types= getTypes(input);
		String type= null;
		if (isHomogenous(types)) {
			type= normalizeCase(types[0]);
			initializeRegistries();
			List<ViewerDescriptor> list = fStructureMergeViewers.searchAll(type);
			if (list != null)
				if (list.contains(vd))
					return type;
			String alias= getStructureViewerAlias(type);
			if (alias != null) {
				list = fStructureMergeViewers.searchAll(alias);
				if (list != null)
					if (list.contains(vd))
						return alias;
			}
		}

		return null;
	}
}
