blob: aca4cbd7ebaf5ec3bed98dab211b80fe3854e4f9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2014 Obeo 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.logical;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Sets;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.compare.ide.ui.logical.SynchronizationModel;
/**
* This will be used to represent an EMF resource's mapping. It will allow us to properly resolve the whole
* logical model of that EMF resource and return the proper traversal so that 'model-aware' tools can work on
* the whole logical model instead of considering only single files.
*
* @author <a href="mailto:laurent.goubet@obeo.fr">laurent Goubet</a>
*/
public class EMFResourceMapping extends ResourceMapping {
/** The resource from which this mapping has been initialized. */
private final IResource resource;
/** Context with which this mapping was initially created. */
private final ResourceMappingContext initialContext;
/** The actual logical model underlying this mapping. */
private final SynchronizationModel synchronizationModel;
/** The Model provider for which this mapping has been created. */
private final String providerId;
/** Keeps track of the latest model computed from this mapping. */
private SynchronizationModel latestModel;
/**
* Instantiates our mapping given its underlying physical {@link IResource}.
*
* @param resource
* The physical resource of this mapping.
* @param initialContext
* The context with which this mapping was initially created.
* @param traversal
* The pre-computed local traversal composing this resource's logical model.
* @param providerId
* The Model provider for which this mapping should be created.
*/
public EMFResourceMapping(IResource resource, ResourceMappingContext initialContext,
SynchronizationModel synchronizationModel, String providerId) {
this.resource = checkNotNull(resource);
this.initialContext = checkNotNull(initialContext);
this.synchronizationModel = checkNotNull(synchronizationModel);
this.providerId = checkNotNull(providerId);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.core.resources.mapping.ResourceMapping#getModelObject()
*/
@Override
public Object getModelObject() {
return synchronizationModel;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.core.resources.mapping.ResourceMapping#getModelProviderId()
*/
@Override
public String getModelProviderId() {
return providerId;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.core.resources.mapping.ResourceMapping#getTraversals(org.eclipse.core.resources.mapping.ResourceMappingContext,
* org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public ResourceTraversal[] getTraversals(ResourceMappingContext context, IProgressMonitor monitor)
throws CoreException {
final SynchronizationModel syncModel;
if (context == initialContext || !(resource instanceof IFile)) {
syncModel = synchronizationModel;
} else {
SynchronizationModel temp = null;
try {
temp = ((EMFModelProvider)getModelProvider()).getOrComputeLogicalModel((IFile)resource,
context, monitor);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
temp = synchronizationModel;
}
syncModel = temp;
}
latestModel = syncModel;
return convertToTraversal(syncModel);
}
private ResourceTraversal[] convertToTraversal(SynchronizationModel syncModel) {
final Set<IResource> resources = syncModel.getResources();
final IResource[] resourcesArray = resources.toArray(new IResource[resources.size()]);
return new ResourceTraversal[] {
new ResourceTraversal(resourcesArray, IResource.DEPTH_ZERO, IResource.NONE), };
}
private static ResourceTraversal[] createSingletonTraversal(IResource aResource) {
final ResourceTraversal singletonTraversal = new ResourceTraversal(new IResource[] {aResource, },
IResource.DEPTH_ONE, IResource.NONE);
return new ResourceTraversal[] {singletonTraversal, };
}
/**
* Returns the latest synchronization model built from a call to
* {@link #getTraversals(ResourceMappingContext, IProgressMonitor)}.
* <p>
* Note that this will return <code>null</code> until
* {@link #getTraversals(ResourceMappingContext, IProgressMonitor)} has been called at least once.
* </p>
* <p>
* This internal API is not meant to be used outside of EMF Compare.
* </p>
*
* @return The latest synchronization model built from a call to
* {@link #getTraversals(ResourceMappingContext, IProgressMonitor)}.
* @noreference This method is not intended to be referenced by clients.
*/
public final SynchronizationModel getLatestModel() {
return latestModel;
}
/** {@inheritDoc} */
@Override
public boolean equals(Object other) {
if (other instanceof EMFResourceMapping) {
return synchronizationModel.equals(((EMFResourceMapping)other).synchronizationModel);
}
return false;
}
/** {@inheritDoc} */
@Override
public int hashCode() {
return synchronizationModel.hashCode();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.core.resources.mapping.ResourceMapping#getProjects()
*/
@Override
public IProject[] getProjects() {
final Set<IProject> projects = Sets.newLinkedHashSet();
if (synchronizationModel.getDiagnostic().getSeverity() >= Diagnostic.ERROR) {
return new IProject[] {resource.getProject(), };
}
for (IResource res : synchronizationModel.getResources()) {
projects.add(res.getProject());
}
final IProject[] projectArray = projects.toArray(new IProject[projects.size()]);
return projectArray;
}
}