/******************************************************************************* * 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; } }