/*******************************************************************************
* Copyright (c) 2009 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.core.util.project.observer;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.*;
/**
* The class is a utility class for attaching observers 2 the event of project
* closed.
*
* After a project is deleted and all the observers r notified, the observers r
* removed, because the project cannont be closed again. Currently, there is no
* option 2 attach an observer 2 a closed project. If an observer need 2 be
* attached, upon opening the project, attach the observer.
*/
public class ProjectRemovedObserversAttacher {
private static ProjectRemovedObserversAttacher instance = new ProjectRemovedObserversAttacher();
private Map<IProject, IProjectClosedObserver> project2CompositeProjectChangeObserver = new HashMap<>();
private IResourceChangeListener resourceChangeListener;
public static ProjectRemovedObserversAttacher getInstance() {
return instance;
}
private ProjectRemovedObserversAttacher() {
}
/**
* There is no need for a remove method because oll the observer
* automatically removed when a project is closed
*
* @param project
* @param projectChangeObserver
*/
public boolean addProjectClosedObserver(IProject project, IProjectClosedObserver projectChangeObserver) {
if (resourceChangeListener == null) {
resourceChangeListener = new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta resourceDelta = event.getDelta();
if (resourceDelta == null) {
return;
}
// always the workspace so the children must be projects
IResourceDelta[] affectedChildren = resourceDelta.getAffectedChildren(IResourceDelta.CHANGED);
if (affectedChildren.length > 0) {
handleClosedProjects(affectedChildren);
} else {
affectedChildren = resourceDelta.getAffectedChildren(IResourceDelta.REMOVED);
handleRemovedProjects(affectedChildren);
}
}
};
}
ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceChangeListener);
if (project == null || !project.isAccessible()) {
return false;
}
CompositeProjectChangeObserver compositeProjectChangeObserver = getCompositeProjectChangeObserver(project);
compositeProjectChangeObserver.add(projectChangeObserver);
return true;
}
private void handleRemovedProjects(IResourceDelta[] affectedChildren) {
for (int i = 0; i < affectedChildren.length; i++) {
IResourceDelta resourceDelta = affectedChildren[i];
IResource resource = resourceDelta.getResource();
IProject project = (IProject) resource;
this.notifyProjectClosed(project);
}
}
private void notifyProjectClosed(IProject project) {
getCompositeProjectChangeObserver(project).closed();
removeCompositeProjectChangeObserver(project);
}
private void handleClosedProjects(IResourceDelta[] affectedChildren) {
for (int i = 0; i < affectedChildren.length; i++) {
IResourceDelta resourceDelta = affectedChildren[i];
IResource resource = resourceDelta.getResource();
IProject project = (IProject) resource;
int eventFlags = resourceDelta.getFlags();
if ((eventFlags & IResourceDelta.OPEN) != 0) {
// could be an OPEN or CLOSE
if (!project.isOpen()) {
this.notifyProjectClosed(project);
}
}
}
}
private void removeCompositeProjectChangeObserver(IProject project) {
CompositeProjectChangeObserver compositeProjectChangeObserver = (CompositeProjectChangeObserver) project2CompositeProjectChangeObserver
.remove(project);
compositeProjectChangeObserver.clear();
if (project2CompositeProjectChangeObserver.isEmpty()) {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(resourceChangeListener);
}
}
private CompositeProjectChangeObserver getCompositeProjectChangeObserver(IProject project) {
Object object = project2CompositeProjectChangeObserver.get(project);
if (object == null) {
CompositeProjectChangeObserver compositeProjectChangeObserver = new CompositeProjectChangeObserver();
project2CompositeProjectChangeObserver.put(project, compositeProjectChangeObserver);
return compositeProjectChangeObserver;
}
return (CompositeProjectChangeObserver) object;
}
}