blob: 3043a8fa9f8ca18d3f5ba666ec6247fdeb4a67aa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.internal.ui.mapping;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.mapping.ModelProvider;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.team.core.mapping.ISynchronizationScope;
import org.eclipse.team.core.mapping.ISynchronizationScopeParticipant;
import org.eclipse.team.internal.ui.TeamUIPlugin;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
public class ResourceModelScopeParticipant implements
ISynchronizationScopeParticipant, IResourceChangeListener, IPropertyChangeListener {
private final ModelProvider provider;
private final ISynchronizationScope scope;
public ResourceModelScopeParticipant(ModelProvider provider, ISynchronizationScope scope) {
this.provider = provider;
this.scope = scope;
if (hasWorkspaceMapping()) {
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
}
if (hasWorkingSetMappings()) {
PlatformUI.getWorkbench().getWorkingSetManager().addPropertyChangeListener(this);
}
}
private boolean hasWorkingSetMappings() {
ResourceMapping[] mappings = scope.getMappings(provider.getDescriptor().getId());
for (int i = 0; i < mappings.length; i++) {
ResourceMapping mapping = mappings[i];
Object modelObject = mapping.getModelObject();
if (modelObject instanceof IWorkingSet) {
return true;
}
}
return false;
}
private boolean hasWorkspaceMapping() {
ResourceMapping[] mappings = scope.getMappings(provider.getDescriptor().getId());
for (int i = 0; i < mappings.length; i++) {
ResourceMapping mapping = mappings[i];
Object modelObject = mapping.getModelObject();
if (modelObject instanceof IResource) {
IResource resource = (IResource) modelObject;
if (resource.getType() == IResource.ROOT) {
return true;
}
} else if (modelObject instanceof ModelProvider) {
ModelProvider provider = (ModelProvider) modelObject;
if (provider.getId().equals(ModelProvider.RESOURCE_MODEL_PROVIDER_ID)) {
return true;
}
}
}
return false;
}
@Override
public ResourceMapping[] handleContextChange(
ISynchronizationScope scope, IResource[] resources,
IProject[] projects) {
Set<ResourceMapping> result = new HashSet<>();
for (int i = 0; i < projects.length; i++) {
IProject project = projects[i];
collectMappings(project, result);
}
return result.toArray(new ResourceMapping[result.size()]);
}
private void collectMappings(IProject project, Set<ResourceMapping> result) {
ResourceMapping[] mappings = scope.getMappings(provider.getDescriptor().getId());
for (int i = 0; i < mappings.length; i++) {
ResourceMapping mapping = mappings[i];
boolean refresh = false;
Object modelObject = mapping.getModelObject();
if (modelObject instanceof IWorkingSet) {
IWorkingSet set = (IWorkingSet)modelObject;
IAdaptable[] elements = set.getElements();
for (int j = 0; j < elements.length; j++) {
IAdaptable adaptable = elements[j];
ResourceMapping m = Adapters.adapt(adaptable, ResourceMapping.class);
if (m != null) {
IProject[] p = m.getProjects();
for (int k = 0; k < p.length; k++) {
IProject mp = p[k];
if (mp.equals(project)) {
refresh = true;
break;
}
}
}
if (refresh)
break;
}
} else if (modelObject instanceof IResource) {
IResource resource = (IResource) modelObject;
if (resource.getType() == IResource.ROOT) {
refresh = true;
}
} else if (modelObject instanceof ModelProvider) {
ModelProvider mp = (ModelProvider) modelObject;
try {
ResourceMapping[] list = mp.getMappings(project, ResourceMappingContext.LOCAL_CONTEXT, null);
if (list.length > 0) {
refresh = true;
}
} catch (CoreException e) {
TeamUIPlugin.log(e);
}
}
if (refresh) {
result.add(mapping);
}
}
}
@Override
public void dispose() {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
if (PlatformUI.isWorkbenchRunning())
PlatformUI.getWorkbench().getWorkingSetManager().removePropertyChangeListener(this);
}
@Override
public void resourceChanged(IResourceChangeEvent event) {
// Only interested in project additions and removals
Set<ResourceMapping> result = new HashSet<>();
IResourceDelta[] children = event.getDelta().getAffectedChildren();
for (int i = 0; i < children.length; i++) {
IResourceDelta delta = children[i];
IResource resource = delta.getResource();
if (resource.getType() == IResource.PROJECT
&& ((delta.getKind() & (IResourceDelta.ADDED | IResourceDelta.REMOVED)) != 0
|| (delta.getFlags() & IResourceDelta.OPEN) != 0)) {
if (isInContext(resource))
collectMappings((IProject)resource, result);
}
}
if (!result.isEmpty())
fireChange(result.toArray(new ResourceMapping[result.size()]));
}
private boolean isInContext(IResource resource) {
IProject[] projects = scope.getProjects();
for (int i = 0; i < projects.length; i++) {
IProject project = projects[i];
if (project.equals(resource.getProject())) {
return true;
}
}
return false;
}
private void fireChange(ResourceMapping[] mappings) {
scope.refresh(mappings);
}
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty() == IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE) {
IWorkingSet newSet = (IWorkingSet) event.getNewValue();
ResourceMapping[] mappings = scope.getMappings(provider.getDescriptor().getId());
for (int i = 0; i < mappings.length; i++) {
ResourceMapping mapping = mappings[i];
if (newSet == mapping.getModelObject()) {
fireChange(new ResourceMapping[] { mapping });
}
}
} else if(event.getProperty() == IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE) {
// TODO: Need to update the participant description somehow
//firePropertyChangedEvent(new PropertyChangeEvent(this, NAME, null, event.getNewValue()));
}
}
}