/** * Copyright (c) 2015-2016 Intel 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: * Stephane Bouchet (Intel Corporation) - initial API and implementation * Olivier Constant (Thales Global Services) - tight integration */ package org.eclipse.emf.diffmerge.connector.core.ext; import java.io.InputStream; import org.eclipse.compare.ISharedDocumentAdapter; import org.eclipse.compare.ITypedElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFileState; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IStorage; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.diffmerge.connector.core.EMFDiffMergeCoreConnectorPlugin; import org.eclipse.emf.diffmerge.connector.core.Messages; import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipse.emf.ecore.resource.impl.ExtensibleURIConverterImpl; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.core.variants.IResourceVariant; import org.eclipse.ui.IEditorInput; /** * A base scope definition factory for file revisions in histories. */ public abstract class AbstractRevisionScopeDefinitionFactory extends AbstractURIConvertingScopeDefinitionFactory { /** * @see org.eclipse.emf.diffmerge.ui.specification.ext.URIScopeDefinitionFactory#convertToURI(java.lang.Object) */ @Override protected URI convertToURI(Object entrypoint_p) { URI result = null; if (entrypoint_p instanceof ITypedElement) { IFileRevision revision = getRevision((ITypedElement)entrypoint_p); if (revision != null) try { result = getURIForRevision(revision); } catch (CoreException e) { EMFDiffMergeCoreConnectorPlugin.getDefault().getLog().log( new Status(IStatus.ERROR, EMFDiffMergeCoreConnectorPlugin.getDefault().getPluginId(), e.getMessage(), e)); } } if (result == null) result = super.convertToURI(entrypoint_p); return result; } /** * @see org.eclipse.emf.diffmerge.ui.specification.ext.URIScopeDefinitionFactory#getLabel() */ @Override public String getLabel() { return Messages.AbstractRevisionScopeDefinitionFactory_Label; } /** * @see org.eclipse.emf.diffmerge.ui.specification.ext.URIScopeDefinitionFactory#getLabelFor(java.lang.Object) */ @Override protected String getLabelFor(Object entrypoint_p) { String result = null; if (entrypoint_p instanceof ITypedElement) { ITypedElement typedElement = (ITypedElement)entrypoint_p; IFileRevision revision = getRevision(typedElement); if (revision != null) result = getLabelForRevision(revision, typedElement); } if (result == null) result = super.getLabelFor(entrypoint_p); return result; } /** * Return a a user-friendly label for the given revision extracted from the given * typed element, if applicable * @param revision_p a non-null revision * @param entrypoint_p a non-null typed element * @return a potentially null string */ protected String getLabelForRevision(IFileRevision revision_p, ITypedElement entrypoint_p) { return revision_p.getContentIdentifier(); } /** * Return the file revision associated to the given typed element, if any * @param entrypoint_p a non-null typed element * @return a potentially null object */ @SuppressWarnings("cast") // Compatibility with old versions of Eclipse protected IFileRevision getRevision(ITypedElement entrypoint_p) { IFileRevision result = null; // The Adapter pattern allows avoiding internal APIs if (entrypoint_p instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable)entrypoint_p; ISharedDocumentAdapter adapter = (ISharedDocumentAdapter)adaptable.getAdapter(ISharedDocumentAdapter.class); if (adapter != null) { IEditorInput input = adapter.getDocumentKey(entrypoint_p); if (input != null) result = (IFileRevision)input.getAdapter(IFileRevision.class); } } return result; } /** * Return the storage associated to the given file revision, if any * @param revision_p a non-null revision * @return a potentially null object * @throws CoreException if an error occurs */ protected IStorage getStorage(IFileRevision revision_p) throws CoreException { return revision_p.getStorage(new NullProgressMonitor()); } /** * @see org.eclipse.emf.diffmerge.connector.core.ext.AbstractURIConvertingScopeDefinitionFactory#getStream(java.lang.Object) */ @Override @SuppressWarnings("resource") protected InputStream getStream(Object entrypoint_p) throws CoreException { InputStream result = null; if (entrypoint_p instanceof ITypedElement) { ITypedElement typedElement = (ITypedElement)entrypoint_p; IFileRevision revision = getRevision(typedElement); if (revision != null) { IStorage storage = getStorage(revision); if (storage != null) result = storage.getContents(); } } if (result == null) result = super.getStream(entrypoint_p); return result; } /** * @see org.eclipse.emf.diffmerge.connector.core.ext.AbstractURIConvertingScopeDefinitionFactory#getURIConverter(java.lang.Object) */ @Override protected URIConverter getURIConverter(Object entrypoint_p) { URIConverter result = null; if (entrypoint_p instanceof ITypedElement) { IFileRevision revision = getRevision((ITypedElement)entrypoint_p); if (revision != null) { try { result = getURIConverterForRevision(revision); } catch (CoreException e) { EMFDiffMergeCoreConnectorPlugin.getDefault().logError(e); } } } return result; } /** * Return a URI converter for the given file revision, if possible. * Precondition: isApplicableToRevision(revision_p) * @param revision_p a non-null revision * @return a potentially null object * @throws CoreException if an error occurs */ protected URIConverter getURIConverterForRevision(IFileRevision revision_p) throws CoreException { URIConverter result = null; URI uri = getURIForRevision(revision_p); if (uri != null) { String fullPath = uri.trimSegments(1).toString(); final long timestamp = revision_p.getTimestamp(); // Local history or current revision if (timestamp != -1) result = new LocalHistoryURIConverter(timestamp, fullPath); else result = new ExtensibleURIConverterImpl(); } return result; } /** * Return a URI for the given file revision * @param revision_p a non-null file revision * @return a potentially null URI * @throws CoreException if an error occurs */ protected URI getURIForRevision(IFileRevision revision_p) throws CoreException { URI result = null; IStorage storage = getStorage(revision_p); if (storage instanceof IFile) { // Local resource result = toPlatformURI((IFile) storage); } else if (storage instanceof IFileState) { // Local file revision (local history) IPath fullPath = storage.getFullPath(); IResource res = ResourcesPlugin.getWorkspace().getRoot() .findMember(fullPath); if (res.exists() && res instanceof IFile) result = toPlatformURI((IFile) res); } else if (storage != null) { result = toFileURI(storage.getFullPath().toString()); } return result; } /** * Return the resource variant associated with the given file revision, if any * @param revision_p a non-null revision * @return a potentially null object */ @SuppressWarnings("cast") // Compatibility with old versions of Eclipse protected IResourceVariant getVariant(IFileRevision revision_p) { IResourceVariant result = null; if (revision_p instanceof IAdaptable) result = (IResourceVariant)((IAdaptable)revision_p).getAdapter(IResourceVariant.class); return result; } /** * @see org.eclipse.emf.diffmerge.ui.specification.ext.URIScopeDefinitionFactory#isApplicableTo(java.lang.Object) */ @Override public boolean isApplicableTo(Object entrypoint_p) { boolean result = false; if (entrypoint_p instanceof ITypedElement) { ITypedElement typedElement = (ITypedElement)entrypoint_p; IFileRevision revision = getRevision(typedElement); if (revision != null) result = isApplicableToRevision(revision, typedElement); } return result; } /** * Return whether this scope definition factory is applicable to the given revision * extracted from the given typed element * @param revision_p a non-null revision * @param entrypoint_p a non-null typed element */ protected abstract boolean isApplicableToRevision(IFileRevision revision_p, ITypedElement entrypoint_p); }