Bug 338478: [api] provide UI connector interface
diff --git a/org.eclipse.mylyn.versions.ui/META-INF/MANIFEST.MF b/org.eclipse.mylyn.versions.ui/META-INF/MANIFEST.MF
index 89bb284..b92e475 100644
--- a/org.eclipse.mylyn.versions.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.versions.ui/META-INF/MANIFEST.MF
@@ -12,8 +12,10 @@
  org.eclipse.team.core,
  org.eclipse.core.resources,
  org.eclipse.ui.workbench,
- org.eclipse.jface
+ org.eclipse.jface,
+ org.eclipse.mylyn.commons.core;bundle-version="3.0"
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Bundle-Localization: plugin
-Export-Package: org.eclipse.mylyn.versions.ui;x-internal:=true
+Export-Package: org.eclipse.mylyn.versions.ui;x-internal:=true,
+ org.eclipse.mylyn.versions.ui.spi;x-internal:=true
diff --git a/org.eclipse.mylyn.versions.ui/plugin.xml b/org.eclipse.mylyn.versions.ui/plugin.xml
new file mode 100644
index 0000000..3835f46
--- /dev/null
+++ b/org.eclipse.mylyn.versions.ui/plugin.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension-point id="connectors" name="Scm Ui Connectors" schema="schema/connectors.exsd"/>
+</plugin>
diff --git a/org.eclipse.mylyn.versions.ui/schema/connectors.exsd b/org.eclipse.mylyn.versions.ui/schema/connectors.exsd
new file mode 100644
index 0000000..a29ed24
--- /dev/null
+++ b/org.eclipse.mylyn.versions.ui/schema/connectors.exsd
@@ -0,0 +1,109 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.mylyn.versions.ui" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appinfo>
+         <meta.schema plugin="org.eclipse.mylyn.versions.ui" id="connectors" name="Scm Ui Connectors"/>
+      </appinfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element />
+         </appinfo>
+      </annotation>
+      <complexType>
+         <choice>
+            <element ref="connector" minOccurs="1" maxOccurs="unbounded"/>
+         </choice>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute translatable="true"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="connector">
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="ui" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.mylyn.versions.ui.spi.ScmUiConnector"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="examples"/>
+      </appinfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="apiinfo"/>
+      </appinfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="implementation"/>
+      </appinfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+
+</schema>
diff --git a/org.eclipse.mylyn.versions.ui/src/org/eclipse/mylyn/versions/ui/ScmUi.java b/org.eclipse.mylyn.versions.ui/src/org/eclipse/mylyn/versions/ui/ScmUi.java
index a55fb6d..66b1114 100644
--- a/org.eclipse.mylyn.versions.ui/src/org/eclipse/mylyn/versions/ui/ScmUi.java
+++ b/org.eclipse.mylyn.versions.ui/src/org/eclipse/mylyn/versions/ui/ScmUi.java
@@ -7,17 +7,34 @@
  *
  * Contributors:
  *     Tasktop Technologies - initial API and implementation
+ *     Alvaro Sanchez-Leon - Extended to include resolution of ui connectors
  *******************************************************************************/
 
 package org.eclipse.mylyn.versions.ui;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
 import org.eclipse.compare.CompareUI;
 import org.eclipse.compare.ITypedElement;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.jface.util.OpenStrategy;
+import org.eclipse.mylyn.commons.core.StatusHandler;
+import org.eclipse.mylyn.versions.ui.spi.ScmUiConnector;
+import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.graphics.Image;
+import org.eclipse.team.core.RepositoryProvider;
 import org.eclipse.team.core.history.IFileRevision;
 import org.eclipse.team.internal.core.history.LocalFileRevision;
 import org.eclipse.team.internal.ui.history.CompareFileRevisionEditorInput;
@@ -29,6 +46,9 @@
  * @author Steffen Pingel
  */
 public class ScmUi {
+	private static HashMap<String, ScmUiConnector> connectorById = new HashMap<String, ScmUiConnector>();
+
+	private static final String ID_PLUGIN = "org.eclipse.mylyn.versions.ui"; //$NON-NLS-1$
 
 	private static class EmptyTypedElement implements ITypedElement {
 
@@ -64,6 +84,11 @@
 		return null;
 	}
 
+	/**
+	 * @param page
+	 * @param file1
+	 * @param file2
+	 */
 	public static void openCompareEditor(IWorkbenchPage page, IFileRevision file1, IFileRevision file2) {
 		Assert.isNotNull(file2);
 
@@ -90,4 +115,81 @@
 		CompareUI.openCompareEditor(input, OpenStrategy.activateOnOpen());
 	}
 
+	/**
+	 * @return
+	 */
+	public static List<ScmUiConnector> getAllRegisteredUiConnectors() {
+		List<ScmUiConnector> scmUiConnectors = new ArrayList<ScmUiConnector>();
+		String[] teamProviderIds = RepositoryProvider.getAllProviderTypeIds();
+		for (String providerId : teamProviderIds) {
+			ScmUiConnector connector = getScmUiConnectorById(providerId);
+			if (connector != null) {
+				scmUiConnectors.add(connector);
+			}
+		}
+		return scmUiConnectors;
+	}
+
+	/**
+	 * @param resource
+	 * @return
+	 */
+	public static ScmUiConnector getUiConnector(IResource resource) {
+		if (!RepositoryProvider.isShared(resource.getProject())) {
+			return null;
+		}
+
+		RepositoryProvider provider = RepositoryProvider.getProvider(resource.getProject());
+		return getScmUiConnectorById(provider.getID());
+	}
+
+	private synchronized static ScmUiConnector getScmUiConnectorById(String id) {
+		ScmUiConnector connector = connectorById.get(id);
+		if (connector == null) {
+			connector = loadConnector(id);
+			connectorById.put(id, connector);
+		}
+		return connector;
+	}
+
+	private static ScmUiConnector loadConnector(String id) {
+		Assert.isNotNull(id);
+		MultiStatus result = new MultiStatus(ScmUi.ID_PLUGIN, 0, "Scm ui connectors failed to load.", null); //$NON-NLS-1$
+
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IExtensionPoint connectorsExtensionPoint = registry.getExtensionPoint(ScmUi.ID_PLUGIN + ".connectors"); //$NON-NLS-1$
+		IExtension[] extensions = connectorsExtensionPoint.getExtensions();
+		for (IExtension extension : extensions) {
+			IConfigurationElement[] elements = extension.getConfigurationElements();
+			for (IConfigurationElement element : elements) {
+				if (id.equals(element.getAttribute("id"))) { //$NON-NLS-1$
+					try {
+						Object object = element.createExecutableExtension("ui"); //$NON-NLS-1$
+						if (object instanceof ScmUiConnector) {
+							return (ScmUiConnector) object;
+						} else {
+							result.add(new Status(
+									IStatus.ERROR,
+									ScmUi.ID_PLUGIN,
+									NLS.bind(
+											"Connector ui ''{0}'' does not extend expected class for extension contributed by {1}", //$NON-NLS-1$
+											object.getClass().getCanonicalName(), element.getContributor().getName())));
+						}
+					} catch (Throwable e) {
+						result.add(new Status(
+								IStatus.ERROR,
+								ScmUi.ID_PLUGIN,
+								NLS.bind(
+										"Connector core failed to load for extension contributed by {0}", element.getContributor().getName()), e)); //$NON-NLS-1$
+					}
+				}
+			}
+		}
+
+		if (!result.isOK()) {
+			StatusHandler.log(result);
+		}
+
+		return null;
+	}
 }
diff --git a/org.eclipse.mylyn.versions.ui/src/org/eclipse/mylyn/versions/ui/spi/ScmUiConnector.java b/org.eclipse.mylyn.versions.ui/src/org/eclipse/mylyn/versions/ui/spi/ScmUiConnector.java
new file mode 100644
index 0000000..8ea0e4d
--- /dev/null
+++ b/org.eclipse.mylyn.versions.ui/src/org/eclipse/mylyn/versions/ui/spi/ScmUiConnector.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Ericsson
+ * 
+ * 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
+ * 
+ * Description:
+ * 
+ * Contributors:
+ *   Alvaro Sanchez-Leon - Initial API and Implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.versions.ui.spi;
+
+import javax.swing.ProgressMonitor;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.mylyn.versions.core.ChangeSet;
+import org.eclipse.mylyn.versions.core.ScmRepository;
+
+/**
+ * @author alvsan09
+ */
+public interface ScmUiConnector {
+	/**
+	 * Derive changes for a given repository and narrow down the selection to the ones related to the option resource provided.
+	 * This method is suitable to open a UI Wizard to reduce the focus even more, driven by user selection.
+	 * @param repo
+	 * @param resource
+	 * @param monitor
+	 * @return
+	 */
+	public ChangeSet getChangeSet(ScmRepository repo, IResource resource, ProgressMonitor monitor);
+}