/*******************************************************************************
* 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.client.ui.ide.generatedelementlistener;
import java.util.ArrayList;
import java.util.Collection;
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.listeners.AbstractGeneratedElementListener;
/**
* Listens all the generated element (must be on the workspace) and warn the synchronizer when one of them
* change.
*
* @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
* @author <a href="mailto:william.piers@obeo.fr">William Piers</a>
*/
public class IDEGeneratedElementListener extends AbstractGeneratedElementListener implements IResourceChangeListener {
/**
* {@link URI}s of resources to ignore.
*/
private Collection<URI> resourcesToIgnore;
/**
* IDEGeneratedElementListener constructor.
*/
public IDEGeneratedElementListener() {
super();
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.addResourceChangeListener(this);
resourcesToIgnore = new ArrayList<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);
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.client.synchronizer.listeners.GeneratedElementListener#dispose()
*/
public void dispose() {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.removeResourceChangeListener(this);
}
/**
* Creates a new DeltaVisitor that will be used to analyse workspaces delta and determine changed
* resources.
*
* @return a new DeltaVisitor that will be used to analyse workspaces delta.
*/
protected IDEGeneratedElementListenerDeltaVisitor createDeltaVisitor() {
return new IDEGeneratedElementListenerDeltaVisitor(listenedElementsURIs);
}
/**
* Sends a notification to the synchronizer for each detected changedResource.
*
* @param changedResources
* the list of listened resources that have changed
*/
protected void treatChangedResources(Collection<URI> changedResources) {
// TODO construct a proper change Notification
if (!changedResources.isEmpty()) {
this.synchronizer.handleChangeNotification(null);
}
}
/**
* 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 IDEGeneratedElementListenerDeltaVisitor visitor = createDeltaVisitor();
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
}
}
}