blob: 00a2f4290b98a25e9b29ba5275c96db5c339f912 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 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.mylyn.docs.intent.retro;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.URI;
import org.eclipse.mylyn.docs.intent.client.synchronizer.SynchronizerRepositoryClient;
import org.eclipse.mylyn.docs.intent.client.synchronizer.api.contribution.ISynchronizerExtension;
import org.eclipse.mylyn.docs.intent.client.synchronizer.api.contribution.ISynchronizerExtensionRegistry;
import org.eclipse.mylyn.docs.intent.client.synchronizer.listeners.AbstractGeneratedElementListener;
public class RetroGeneratedElementListener extends AbstractGeneratedElementListener implements ISynchronizerExtension, IResourceChangeListener {
public static final String RETRO_SCHEME = "retro";
protected Map<URI, Set<SynchronizerRepositoryClient>> uriToSynchronizers = Maps.newLinkedHashMap();
private ArrayList<URI> resourcesToIgnore;
/**
* Default constructor.
*/
public RetroGeneratedElementListener() {
super();
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.addResourceChangeListener(this);
resourcesToIgnore = new ArrayList<URI>();
}
/**
* Returns the active instance.
*
* @return the active instance
*/
public static RetroGeneratedElementListener getInstance() {
Iterable<RetroGeneratedElementListener> synchronizerExtensions = Iterables.filter(
ISynchronizerExtensionRegistry.getSynchronizerExtensions(RETRO_SCHEME),
RetroGeneratedElementListener.class);
if (synchronizerExtensions.iterator().hasNext()) {
return synchronizerExtensions.iterator().next();
}
return null;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.client.synchronizer.api.contribution.ISynchronizerExtension#addListenedElements(org.eclipse.mylyn.docs.intent.client.synchronizer.SynchronizerRepositoryClient,
* java.util.Set)
*/
public void addListenedElements(SynchronizerRepositoryClient synchronizer, Set<URI> listenedElementsURIs) {
for (URI uri : listenedElementsURIs) {
if (!(uriToSynchronizers.containsKey(uri))) {
uriToSynchronizers.put(uri, Sets.<SynchronizerRepositoryClient> newLinkedHashSet());
}
uriToSynchronizers.get(uri).add(synchronizer);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.client.synchronizer.api.contribution.ISynchronizerExtension#removeListenedElements(org.eclipse.mylyn.docs.intent.client.synchronizer.SynchronizerRepositoryClient,
* java.util.Set)
*/
public void removeListenedElements(SynchronizerRepositoryClient synchronizer,
Set<URI> listenedElementsURIs) {
for (URI uri : listenedElementsURIs) {
uriToSynchronizers.remove(uri);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
*/
public void resourceChanged(IResourceChangeEvent event) {
if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
final IResourceDelta rootDelta = event.getDelta();
// We get the delta related to the Repository (if any)
// If any resource of the repository has changed
if (rootDelta != null) {
// We launch the analysis of the delta in a new thread
analyseWorkspaceDelta(rootDelta);
}
}
}
/**
* Analyzes the given IResourceDelta in a new thread ; reloads the resources if needed and send
* notification to the registered Session listeners.
*
* @param repositoryDelta
* the IResourceDelta to analyse
*/
private void analyseWorkspaceDelta(IResourceDelta repositoryDelta) {
// We first create a DeltaVisitor on the repository Path
final RetroGeneratedElementListenerDeltaVisitor visitor = new RetroGeneratedElementListenerDeltaVisitor(
listenedElementsURIs);
try {
// We visit the given delta using this visitor
repositoryDelta.accept(visitor);
// We get the changed and removed Resources
Collection<URI> changedResources = new ArrayList<URI>();
if (!visitor.getRemovedResources().isEmpty()) {
changedResources.addAll(visitor.getRemovedResources());
}
for (URI changedResource : visitor.getChangedResources()) {
// If the resource is contained in the resourcesToIgnore list, it means
// that we should ignore this notification ; however we remove this resource
// from this list so that we'll treat the next notifications
if (!resourcesToIgnore.contains(changedResource)) {
changedResources.add(changedResource);
// resourcesToIgnore.add(changedResource);
} else {
resourcesToIgnore.remove(changedResource);
}
}
// Finally, we treat each removed or changed resource.
treatChangedResources(changedResources);
} catch (CoreException e) {
// TODO define a standard reaction to this exception :
// - relaunch the session
// - try to visit the delta again
// - do nothing
e.printStackTrace();
}
}
protected void treatChangedResources(Collection<URI> changedResources) {
Set<SynchronizerRepositoryClient> synchronizersToNotify = Sets.newLinkedHashSet();
for (URI uri : changedResources) {
Set<SynchronizerRepositoryClient> listeningSynchronizers = uriToSynchronizers.get(uri);
if (listeningSynchronizers != null) {
synchronizersToNotify.addAll(listeningSynchronizers);
}
}
for (SynchronizerRepositoryClient listeningSynchronizer : synchronizersToNotify) {
listeningSynchronizer.handleChangeNotification(null);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.client.synchronizer.listeners.GeneratedElementListener#dispose()
*/
public void dispose() {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.removeResourceChangeListener(this);
}
}