diff options
author | Laurent Goubet | 2013-06-18 08:40:27 +0000 |
---|---|---|
committer | Laurent Goubet | 2013-06-18 10:57:15 +0000 |
commit | 9dd372130711bc88c17106f685bf03afe205b8f4 (patch) | |
tree | 669d814ac057c67e3040f1b40282ad5cb4277b62 /plugins/org.eclipse.emf.compare.ide.ui/src | |
parent | be943cac6f92d75296b4ccd141124bc8e8556de9 (diff) | |
download | org.eclipse.emf.compare-9dd372130711bc88c17106f685bf03afe205b8f4.tar.gz org.eclipse.emf.compare-9dd372130711bc88c17106f685bf03afe205b8f4.tar.xz org.eclipse.emf.compare-9dd372130711bc88c17106f685bf03afe205b8f4.zip |
Introduce extension point for the model resolvers.
Change-Id: I4e6e785d1e750fa089059e622feb6cdf457c02bc
Diffstat (limited to 'plugins/org.eclipse.emf.compare.ide.ui/src')
11 files changed, 441 insertions, 11 deletions
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/EMFCompareIDEUIPlugin.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/EMFCompareIDEUIPlugin.java index fabc0c118..ea0a369d0 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/EMFCompareIDEUIPlugin.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/EMFCompareIDEUIPlugin.java @@ -10,8 +10,14 @@ *******************************************************************************/ package org.eclipse.emf.compare.ide.ui.internal; +import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; +import org.eclipse.emf.compare.ide.ui.internal.logical.IModelResolverRegistry; +import org.eclipse.emf.compare.ide.ui.internal.logical.ModelResolverRegistryImpl; +import org.eclipse.emf.compare.ide.ui.internal.logical.ModelResolverRegistryListener; +import org.eclipse.emf.compare.rcp.extension.AbstractRegistryEventListener; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; @@ -32,9 +38,18 @@ public class EMFCompareIDEUIPlugin extends AbstractUIPlugin { /** Plug-in's shared instance. */ private static EMFCompareIDEUIPlugin plugin; + /** Model resolvers extension point. */ + private static final String MODEL_RESOLVER_PPID = "modelResolvers"; //$NON-NLS-1$ + /** Manages the images that were loaded by EMF Compare. */ private LocalResourceManager fResourceManager; + /** Listener for the model resolver extension point. */ + private AbstractRegistryEventListener modelResolverRegistryListener; + + /** Registry of model resolvers. */ + private IModelResolverRegistry modelResolverRegistry; + /** Default constructor. */ public EMFCompareIDEUIPlugin() { // Empty constructor @@ -50,6 +65,12 @@ public class EMFCompareIDEUIPlugin extends AbstractUIPlugin { super.start(context); plugin = this; + final IExtensionRegistry globalRegistry = Platform.getExtensionRegistry(); + modelResolverRegistry = new ModelResolverRegistryImpl(); + modelResolverRegistryListener = new ModelResolverRegistryListener(PLUGIN_ID, MODEL_RESOLVER_PPID, + getLog(), modelResolverRegistry); + globalRegistry.addListener(modelResolverRegistryListener); + modelResolverRegistryListener.readRegistry(globalRegistry); } /** @@ -63,6 +84,10 @@ public class EMFCompareIDEUIPlugin extends AbstractUIPlugin { fResourceManager.dispose(); } + final IExtensionRegistry globalRegistry = Platform.getExtensionRegistry(); + globalRegistry.removeListener(modelResolverRegistryListener); + modelResolverRegistry.clear(); + plugin = null; super.stop(context); } @@ -76,6 +101,15 @@ public class EMFCompareIDEUIPlugin extends AbstractUIPlugin { return plugin; } + /** + * Returns the registry containing all known model resolvers. + * + * @return The registry containing all known model resolvers. + */ + public IModelResolverRegistry getModelResolverRegistry() { + return modelResolverRegistry; + } + public ImageDescriptor getImageDescriptor(String path) { return imageDescriptorFromPlugin(EMFCompareIDEUIPlugin.PLUGIN_ID, path); } diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/ide_ui_messages.properties b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/ide_ui_messages.properties index ca16f6dfb..cde0e4743 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/ide_ui_messages.properties +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/ide_ui_messages.properties @@ -11,4 +11,7 @@ ## ! note ! double the apostrophes if you need one in the printed String EMFSynchronizationModel.resolving = Creating EMF Synchronization Model EMFSynchronizationModel.minimizing = Minimizing synchronization model -EMFSynchronizationModel.creatingScope = Creating comparison scope
\ No newline at end of file +EMFSynchronizationModel.creatingScope = Creating comparison scope + +ModelResolveRegistry.invalidResolver = Model resolver class ''{0}'' could not be instantiated. +ModelResolveRegistry.invalidRanking = Ranking of resolver ''{0}'' was not a valid integer : ''{1}''.
\ No newline at end of file diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/EMFResourceMapping.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/EMFResourceMapping.java index 02e1c464a..2298f33df 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/EMFResourceMapping.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/EMFResourceMapping.java @@ -26,6 +26,7 @@ import org.eclipse.core.resources.mapping.ResourceTraversal; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIPlugin;
import org.eclipse.emf.compare.ide.utils.ResourceUtil;
import org.eclipse.emf.compare.ide.utils.StorageTraversal;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
@@ -118,7 +119,8 @@ public class EMFResourceMapping extends ResourceMapping { * detecting a traversal for a file that's been removed locally but is present on the repository is
* not necessary at this point.
*/
- return new ProjectModelResolver().resolveLocalModel(file, monitor);
+ return EMFCompareIDEUIPlugin.getDefault().getModelResolverRegistry().getBestResolverFor(file)
+ .resolveLocalModel(file, monitor);
}
/**
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/IModelResolverRegistry.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/IModelResolverRegistry.java new file mode 100644 index 000000000..d411b2cfd --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/IModelResolverRegistry.java @@ -0,0 +1,54 @@ +/*******************************************************************************
+ * Copyright (c) 2013 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.internal.logical;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.emf.compare.ide.ui.logical.IModelResolver;
+
+/**
+ * This registry will be populated with all IModelResolver instances registered through the associated
+ * extension point.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public interface IModelResolverRegistry {
+ /**
+ * This can be called to retrieve the best model resolver for the given IStorage. "Best", here, means the
+ * highest ranking IModelResolver
+ *
+ * @param sourceStorage
+ * The storage we're trying to resolve the logical model of.
+ * @return The highest ranking resolver that is capable of resolving the logical model of the given
+ * storage.
+ */
+ IModelResolver getBestResolverFor(IStorage sourceStorage);
+
+ /**
+ * Registers a new resolver within this registry instance.
+ *
+ * @param key
+ * Identifier of this resolver.
+ * @param resolver
+ * The resolver to register.
+ */
+ void addResolver(String key, IModelResolver resolver);
+
+ /**
+ * Removes the resolver identified by <code>key</code> from this registry.
+ *
+ * @param key
+ * Identifier of the resolver we are to remove from this registry.
+ */
+ void removeResolver(String key);
+
+ /** Clears out this registry from all registered resolvers. */
+ void clear();
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/LogicalModelResolver.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/LogicalModelResolver.java index 8f71a9530..2e6dc5614 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/LogicalModelResolver.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/LogicalModelResolver.java @@ -23,6 +23,7 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet;
import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIMessages;
+import org.eclipse.emf.compare.ide.ui.logical.AbstractModelResolver;
import org.eclipse.emf.compare.ide.ui.logical.IModelResolver;
import org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor;
import org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor.DiffSide;
@@ -37,7 +38,7 @@ import org.eclipse.emf.compare.ide.utils.StorageURIConverter; *
* @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
*/
-public class LogicalModelResolver implements IModelResolver {
+public class LogicalModelResolver extends AbstractModelResolver {
/**
* {@inheritDoc}
*
@@ -126,6 +127,16 @@ public class LogicalModelResolver implements IModelResolver { }
/**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.logical.IModelResolver#canResolve(org.eclipse.core.resources.IStorage)
+ */
+ public boolean canResolve(IStorage sourceStorage) {
+ // This is our default resolver. It should be able to handle any case.
+ return true;
+ }
+
+ /**
* Checks whether the given set already contains the given storage. We can't rely on contains() since the
* storages override neither hash code nor equals.
*
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ModelResolverRegistryImpl.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ModelResolverRegistryImpl.java new file mode 100644 index 000000000..27c7cded2 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ModelResolverRegistryImpl.java @@ -0,0 +1,93 @@ +/*******************************************************************************
+ * Copyright (c) 2013 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.internal.logical;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.emf.compare.ide.ui.logical.IModelResolver;
+
+/**
+ * This registry will be used to keep track of all {@link IModelResolver}s that have been registered against
+ * the extension point. Clients can query the registry to determine which resolver should be used for a given
+ * resource.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public final class ModelResolverRegistryImpl implements IModelResolverRegistry {
+ /** Keeps track of the extensions providing model resolvers. */
+ private final Map<String, IModelResolver> resolvers;
+
+ /** Initializes our registry. */
+ public ModelResolverRegistryImpl() {
+ this.resolvers = new ConcurrentHashMap<String, IModelResolver>();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.logical.IModelResolverRegistry#getBestResolverFor(org.eclipse.core.resources.IStorage)
+ */
+ public IModelResolver getBestResolverFor(IStorage sourceStorage) {
+ IModelResolver resolver = null;
+ for (IModelResolver candidate : resolvers.values()) {
+ if (candidate.canResolve(sourceStorage) && ranking(resolver) < ranking(candidate)) {
+ resolver = candidate;
+ }
+ }
+ return resolver;
+ }
+
+ /**
+ * Returns a ranking for the given resolver, which can be <code>null</code>.
+ *
+ * @param resolver
+ * The resolver we need a ranking for.
+ * @return Ranking of the given resolver, <code>-1</code> if that resolver is <code>null</code>.
+ */
+ private static final int ranking(IModelResolver resolver) {
+ if (resolver == null) {
+ return -1;
+ }
+ return resolver.getRanking();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.logical.IModelResolverRegistry#addResolver(java.lang.String,
+ * org.eclipse.emf.compare.ide.ui.logical.IModelResolver)
+ */
+ public void addResolver(String key, IModelResolver resolver) {
+ resolvers.put(checkNotNull(key), checkNotNull(resolver));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.logical.IModelResolverRegistry#removeResolver(java.lang.String)
+ */
+ public void removeResolver(String key) {
+ resolvers.remove(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.logical.IModelResolverRegistry#clear()
+ */
+ public void clear() {
+ resolvers.clear();
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ModelResolverRegistryListener.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ModelResolverRegistryListener.java new file mode 100644 index 000000000..e628f72ea --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ModelResolverRegistryListener.java @@ -0,0 +1,117 @@ +/*******************************************************************************
+ * Copyright (c) 2013 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.internal.logical;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIMessages;
+import org.eclipse.emf.compare.ide.ui.logical.IModelResolver;
+import org.eclipse.emf.compare.rcp.extension.AbstractRegistryEventListener;
+
+/**
+ * This listener will react to changes against our model resolver extension point, allowing us to be in sync
+ * with plugin activation and deactivation.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public class ModelResolverRegistryListener extends AbstractRegistryEventListener {
+ /** The "resolver" tag of our extension point. */
+ private static final String TAG_RESOLVER = "resolver"; //$NON-NLS-1$
+
+ /** The "class" attribute of our resolver tag. */
+ private static final String ATTRIBUTE_CLASS = "class"; //$NON-NLS-1$
+
+ /** The "ranking" attribute of our resolver tag. */
+ private static final String ATTRIBUTE_RANKING = "ranking"; //$NON-NLS-1$
+
+ /** The actual registry this listener will alter. */
+ private final IModelResolverRegistry registry;
+
+ /**
+ * Initialize a registry event listener for our model resolvers.
+ *
+ * @param pluginID
+ * ID of the plugin contributing the extension point to monitor.
+ * @param extensionPointID
+ * Actual id of the extension point to monitor.
+ * @param log
+ * Log in which errors/warning should be logged.
+ * @param registry
+ * The actual store of model resolvers this registry will alter.
+ */
+ public ModelResolverRegistryListener(String pluginID, String extensionPointID, ILog log,
+ IModelResolverRegistry registry) {
+ super(pluginID, extensionPointID, log);
+ this.registry = registry;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.rcp.extension.AbstractRegistryEventListener#addedValid(org.eclipse.core.runtime.IConfigurationElement)
+ */
+ @Override
+ protected boolean addedValid(IConfigurationElement element) {
+ if (element.getName().equals(TAG_RESOLVER)) {
+ final String className = element.getAttribute(ATTRIBUTE_CLASS);
+ IModelResolver resolver;
+ try {
+ resolver = (IModelResolver)element.createExecutableExtension(ATTRIBUTE_CLASS);
+ } catch (CoreException e) {
+ final String message = EMFCompareIDEUIMessages.getString(
+ "ModelResolveRegistry.invalidResolver", className); //$NON-NLS-1$
+ log(element, message, e);
+ return false;
+ }
+
+ assert resolver != null;
+ final String rankingStr = element.getAttribute(ATTRIBUTE_RANKING);
+ int ranking = -1;
+ try {
+ ranking = Integer.parseInt(rankingStr);
+ } catch (NumberFormatException e) {
+ log(IStatus.ERROR, element, EMFCompareIDEUIMessages.getString(
+ "ModelResolveRegistry.invalidRanking", className, rankingStr)); //$NON-NLS-1$
+ }
+ resolver.setRanking(ranking);
+
+ registry.addResolver(className, resolver);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.rcp.extension.AbstractRegistryEventListener#removedValid(org.eclipse.core.runtime.IConfigurationElement)
+ */
+ @Override
+ protected boolean removedValid(IConfigurationElement element) {
+ final String className = element.getAttribute(ATTRIBUTE_CLASS);
+ registry.removeResolver(className);
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.rcp.extension.AbstractRegistryEventListener#validateExtensionElement(org.eclipse.core.runtime.IConfigurationElement)
+ */
+ @Override
+ protected boolean validateExtensionElement(IConfigurationElement element) {
+ // Don't work twice as much, validate as we add.
+ // Removing cannot fail.
+ return true;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ProjectModelResolver.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ProjectModelResolver.java index 108ce54f1..175e6578e 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ProjectModelResolver.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ProjectModelResolver.java @@ -152,6 +152,20 @@ public class ProjectModelResolver extends LogicalModelResolver { }
/**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#canResolve(org.eclipse.core.resources.IStorage)
+ */
+ @Override
+ public boolean canResolve(IStorage sourceStorage) {
+ if (sourceStorage instanceof IFile) {
+ IFile file = (IFile)sourceStorage;
+ return file.getProject().isAccessible() && ((IFile)sourceStorage).exists();
+ }
+ return false;
+ }
+
+ /**
* This will be used to resolve the traversal of a file's logical model, given the resource visitor that
* has been used to browse the scope for potential dependencies (by default, the scope is the resource's
* project).
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java index a48219d85..d8c1f98eb 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java @@ -32,6 +32,7 @@ import org.eclipse.compare.ITypedElement; import org.eclipse.compare.structuremergeviewer.DiffTreeViewer; import org.eclipse.compare.structuremergeviewer.ICompareInput; import org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener; +import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; @@ -59,10 +60,12 @@ import org.eclipse.emf.compare.ide.ui.internal.actions.expand.ExpandAllModelActi import org.eclipse.emf.compare.ide.ui.internal.editor.ComparisonScopeInput; import org.eclipse.emf.compare.ide.ui.internal.logical.ComparisonScopeBuilder; import org.eclipse.emf.compare.ide.ui.internal.logical.IdenticalResourceMinimizer; -import org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver; +import org.eclipse.emf.compare.ide.ui.internal.logical.StreamAccessorStorage; import org.eclipse.emf.compare.ide.ui.internal.logical.SubscriberStorageAccessor; import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.provider.ComparisonNode; +import org.eclipse.emf.compare.ide.ui.internal.util.PlatformElementUtil; import org.eclipse.emf.compare.ide.ui.internal.util.SWTUtil; +import org.eclipse.emf.compare.ide.ui.logical.IModelResolver; import org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor; import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin; import org.eclipse.emf.compare.rcp.ui.internal.EMFCompareConstants; @@ -332,13 +335,7 @@ public class EMFCompareStructureMergeViewer extends DiffTreeViewer implements Co final ITypedElement right = input.getRight(); final ITypedElement origin = input.getAncestor(); - IStorageProviderAccessor storageAccessor = null; - if (getSubscriber() != null) { - storageAccessor = new SubscriberStorageAccessor(getSubscriber()); - } - final ComparisonScopeBuilder scopeBuilder = new ComparisonScopeBuilder( - new LogicalModelResolver(), new IdenticalResourceMinimizer(), storageAccessor); - final IComparisonScope scope = scopeBuilder.build(left, right, origin, subMonitor + final IComparisonScope scope = buildComparisonScope(left, right, origin, subMonitor .newChild(85)); final Comparison compareResult = EMFCompare @@ -427,6 +424,36 @@ public class EMFCompareStructureMergeViewer extends DiffTreeViewer implements Co } } + /** + * Constructs the comparison scope corresponding to the given typed elements. + * + * @param left + * Left of the compared elements. + * @param right + * Right of the compared elements. + * @param origin + * Common ancestor of the <code>left</code> and <code>right</code> compared elements. + * @param monitor + * Monitor to report progress on. + * @return The created comparison scope. + */ + private IComparisonScope buildComparisonScope(ITypedElement left, ITypedElement right, + ITypedElement origin, IProgressMonitor monitor) { + IStorageProviderAccessor storageAccessor = null; + if (getSubscriber() != null) { + storageAccessor = new SubscriberStorageAccessor(getSubscriber()); + } + IStorage leftStorage = PlatformElementUtil.findFile(left); + if (leftStorage == null) { + leftStorage = StreamAccessorStorage.fromTypedElement(left); + } + IModelResolver resolver = EMFCompareIDEUIPlugin.getDefault().getModelResolverRegistry() + .getBestResolverFor(leftStorage); + final ComparisonScopeBuilder scopeBuilder = new ComparisonScopeBuilder(resolver, + new IdenticalResourceMinimizer(), storageAccessor); + return scopeBuilder.build(left, right, origin, monitor); + } + void compareInputChanged(ComparisonNode input, IProgressMonitor monitor) { ICompareEditingDomain editingDomain = (ICompareEditingDomain)getCompareConfiguration().getProperty( EMFCompareConstants.EDITING_DOMAIN); diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/logical/AbstractModelResolver.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/logical/AbstractModelResolver.java new file mode 100644 index 000000000..3d3754cf6 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/logical/AbstractModelResolver.java @@ -0,0 +1,43 @@ +/*******************************************************************************
+ * Copyright (c) 2013 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.logical;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * This can be subclassed instead of {@link IModelResolver} to avoid reimplementing common extension-realted
+ * code.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+@Beta
+public abstract class AbstractModelResolver implements IModelResolver {
+ /** Ranking of this resolver. */
+ protected int ranking;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.logical.IModelResolver#getRanking()
+ */
+ public int getRanking() {
+ return ranking;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.logical.IModelResolver#setRanking(int)
+ */
+ public void setRanking(int newRanking) {
+ this.ranking = newRanking;
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/logical/IModelResolver.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/logical/IModelResolver.java index 4ba100137..210437819 100644 --- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/logical/IModelResolver.java +++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/logical/IModelResolver.java @@ -20,6 +20,9 @@ import org.eclipse.emf.compare.ide.utils.StorageTraversal; /**
* This can be used in order to tell EMF Compare how the logical model of a given file can be resolved in its
* entirety.
+ * <p>
+ * Clients can subclass {@link AbstractModelResolver} instead.
+ * </p>
*
* @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
*/
@@ -78,4 +81,33 @@ public interface IModelResolver { * @return A traversal corresponding to all resources composing the given file's logical model.
*/
StorageTraversal resolveLocalModel(IResource resource, IProgressMonitor monitor);
+
+ /**
+ * Ranking of this model resolver. Will be used by EMF Compare to determine which resolver is best for
+ * which kind of resource.
+ *
+ * @return The ranking of this resolver.
+ */
+ int getRanking();
+
+ /**
+ * Sets the ranking of this resolver to the given value. Mainly used by the extension point registration.
+ *
+ * @param newRanking
+ * New ranking for this model resolver.
+ */
+ void setRanking(int newRanking);
+
+ /**
+ * This will be used in order to determine whether this resolver can be used for the given storage. For
+ * each given storage, the resolver with the highest ranking will be selected for resolution. This test
+ * should be fast.
+ *
+ * @param sourceStorage
+ * The resource we're trying to resolve the logical model of. This will always be the "source"
+ * or "left" variant of the compared resource.
+ * @return <code>true</code> if this resolver is capable of handling the given storage, <code>false</code>
+ * otherwise.
+ */
+ boolean canResolve(IStorage sourceStorage);
}
|