/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core;

import java.io.File;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
import org.eclipse.jdt.internal.core.search.AbstractSearchScope;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
import org.eclipse.jdt.internal.core.util.Util;

/**
 * This class is used by <code>JavaModelManager</code> to convert
 * <code>IResourceDelta</code>s into <code>IJavaElementDelta</code>s.
 * It also does some processing on the <code>JavaElement</code>s involved
 * (e.g. closing them or updating classpaths).
 */
public class DeltaProcessor {
	
	static class OutputsInfo {
		int outputCount;
		IPath[] paths;
		int[] traverseModes;
		OutputsInfo(IPath[] paths, int[] traverseModes, int outputCount) {
			this.paths = paths;
			this.traverseModes = traverseModes;
			this.outputCount = outputCount;
		}
		public String toString() {
			if (this.paths == null) return "<none>"; //$NON-NLS-1$
			StringBuffer buffer = new StringBuffer();
			for (int i = 0; i < this.outputCount; i++) {
				buffer.append("path="); //$NON-NLS-1$
				buffer.append(this.paths[i].toString());
				buffer.append("\n->traverse="); //$NON-NLS-1$
				switch (this.traverseModes[i]) {
					case BINARY:
						buffer.append("BINARY"); //$NON-NLS-1$
						break;
					case IGNORE:
						buffer.append("IGNORE"); //$NON-NLS-1$
						break;
					case SOURCE:
						buffer.append("SOURCE"); //$NON-NLS-1$
						break;
					default:
						buffer.append("<unknown>"); //$NON-NLS-1$
				}
				if (i+1 < this.outputCount) {
					buffer.append('\n');
				}
			}
			return buffer.toString();
		}
	}
	
	static class RootInfo {
		char[][] inclusionPatterns;
		char[][] exclusionPatterns;
		JavaProject project;
		IPath rootPath;
		int entryKind;
		IPackageFragmentRoot root;
		RootInfo(JavaProject project, IPath rootPath, char[][] inclusionPatterns, char[][] exclusionPatterns, int entryKind) {
			this.project = project;
			this.rootPath = rootPath;
			this.inclusionPatterns = inclusionPatterns;
			this.exclusionPatterns = exclusionPatterns;
			this.entryKind = entryKind;
		}
		IPackageFragmentRoot getPackageFragmentRoot(IResource resource) {
			if (this.root == null) {
				if (resource != null) {
					this.root = this.project.getPackageFragmentRoot(resource);
				} else {
					Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), this.rootPath, false/*don't check existence*/);
					if (target instanceof IResource) {
						this.root = this.project.getPackageFragmentRoot((IResource)target);
					} else {
						this.root = this.project.getPackageFragmentRoot(this.rootPath.toOSString());
					}
				}
			}
			return this.root;
		}
		boolean isRootOfProject(IPath path) {
			return this.rootPath.equals(path) && this.project.getProject().getFullPath().isPrefixOf(path);
		}
		public String toString() {
			StringBuffer buffer = new StringBuffer("project="); //$NON-NLS-1$
			if (this.project == null) {
				buffer.append("null"); //$NON-NLS-1$
			} else {
				buffer.append(this.project.getElementName());
			}
			buffer.append("\npath="); //$NON-NLS-1$
			if (this.rootPath == null) {
				buffer.append("null"); //$NON-NLS-1$
			} else {
				buffer.append(this.rootPath.toString());
			}
			buffer.append("\nincluding="); //$NON-NLS-1$
			if (this.inclusionPatterns == null) {
				buffer.append("null"); //$NON-NLS-1$
			} else {
				for (int i = 0, length = this.inclusionPatterns.length; i < length; i++) {
					buffer.append(new String(this.inclusionPatterns[i]));
					if (i < length-1) {
						buffer.append("|"); //$NON-NLS-1$
					}
				}
			}
			buffer.append("\nexcluding="); //$NON-NLS-1$
			if (this.exclusionPatterns == null) {
				buffer.append("null"); //$NON-NLS-1$
			} else {
				for (int i = 0, length = this.exclusionPatterns.length; i < length; i++) {
					buffer.append(new String(this.exclusionPatterns[i]));
					if (i < length-1) {
						buffer.append("|"); //$NON-NLS-1$
					}
				}
			}
			return buffer.toString();
		}
	}

	private final static int IGNORE = 0;
	private final static int SOURCE = 1;
	private final static int BINARY = 2;
	
	private final static String EXTERNAL_JAR_ADDED = "external jar added"; //$NON-NLS-1$
	private final static String EXTERNAL_JAR_CHANGED = "external jar changed"; //$NON-NLS-1$
	private final static String EXTERNAL_JAR_REMOVED = "external jar removed"; //$NON-NLS-1$
	private final static String EXTERNAL_JAR_UNCHANGED = "external jar unchanged"; //$NON-NLS-1$
	private final static String INTERNAL_JAR_IGNORE = "internal jar ignore"; //$NON-NLS-1$
	
	private final static int NON_JAVA_RESOURCE = -1;
	public static boolean DEBUG = false;
	public static boolean VERBOSE = false;

	public static final int DEFAULT_CHANGE_EVENT = 0; // must not collide with ElementChangedEvent event masks

	/*
	 * Answer a combination of the lastModified stamp and the size.
	 * Used for detecting external JAR changes
	 */
	public static long getTimeStamp(File file) {
		return file.lastModified() + file.length();
	}
	
	/*
	 * The global state of delta processing.
	 */
	private DeltaProcessingState state;
	
	/*
	 * The Java model manager
	 */
	private JavaModelManager manager;
	
	/*
	 * The <code>JavaElementDelta</code> corresponding to the <code>IResourceDelta</code> being translated.
	 */
	private JavaElementDelta currentDelta;

	/* The java element that was last created (see createElement(IResource)). 
	 * This is used as a stack of java elements (using getParent() to pop it, and 
	 * using the various get*(...) to push it. */
	private Openable currentElement;
		
	/*
	 * Queue of deltas created explicily by the Java Model that
	 * have yet to be fired.
	 */
	public ArrayList javaModelDeltas= new ArrayList();
	
	/*
	 * Queue of reconcile deltas on working copies that have yet to be fired.
	 * This is a table form IWorkingCopy to IJavaElementDelta
	 */
	public HashMap reconcileDeltas = new HashMap();

	/*
	 * Turns delta firing on/off. By default it is on.
	 */
	private boolean isFiring= true;
	
	/*
	 * Used to update the JavaModel for <code>IJavaElementDelta</code>s.
	 */
	private final ModelUpdater modelUpdater = new ModelUpdater();

	/* A set of IJavaProject whose caches need to be reset */
	private HashSet projectCachesToReset = new HashSet();  

	/*
	 * A list of IJavaElement used as a scope for external archives refresh during POST_CHANGE.
	 * This is null if no refresh is needed.
	 */
	private HashSet refreshedElements;
	
	/* A table from IJavaProject to an array of IPackageFragmentRoot.
	 * This table contains the pkg fragment roots of the project that are being deleted.
	 */
	public Map removedRoots;
	
	/* A set of IJavaProject whose package fragment roots need to be refreshed */
	private HashSet rootsToRefresh = new HashSet();
	
	/*
	 * Type of event that should be processed no matter what the real event type is.
	 */
	public int overridenEventType = -1;
		
	public DeltaProcessor(DeltaProcessingState state, JavaModelManager manager) {
		this.state = state;
		this.manager = manager;
	}

	/*
	 * Adds the dependents of the given project to the list of the projects
	 * to update.
	 */
	private void addDependentProjects(IPath projectPath, HashSet result) {
		IJavaProject[] projects = null;
		try {
			projects = this.manager.getJavaModel().getJavaProjects();
		} catch (JavaModelException e) {
			// java model doesn't exist
			return;
		}
		for (int i = 0, length = projects.length; i < length; i++) {
			IJavaProject project = projects[i];
			IClasspathEntry[] classpath = null;
			try {
				classpath = ((JavaProject)project).getExpandedClasspath(true);
			} catch (JavaModelException e) {
				// project doesn't exist: continue with next project
				continue;
			}
			for (int j = 0, length2 = classpath.length; j < length2; j++) {
				IClasspathEntry entry = classpath[j];
					if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
							&& entry.getPath().equals(projectPath)) {
						result.add(project);
					}
				}
			}
	}
	/*
	 * Adds the given element to the list of elements used as a scope for external jars refresh.
	 */
	public void addForRefresh(IJavaElement element) {
		if (this.refreshedElements == null) {
			this.refreshedElements = new HashSet();
		}
		this.refreshedElements.add(element);
	}
	/*
	 * Adds the given child handle to its parent's cache of children. 
	 */
	private void addToParentInfo(Openable child) {
		Openable parent = (Openable) child.getParent();
		if (parent != null && parent.isOpen()) {
			try {
				JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
				info.addChild(child);
			} catch (JavaModelException e) {
				// do nothing - we already checked if open
			}
		}
	}
	/*
	 * Adds the given project and its dependents to the list of the roots to refresh.
	 */
	private void addToRootsToRefreshWithDependents(IJavaProject javaProject) {
		this.rootsToRefresh.add(javaProject);
		this.addDependentProjects(javaProject.getPath(), this.rootsToRefresh);
	}
	/*
	 * Check all external archive (referenced by given roots, projects or model) status and issue a corresponding root delta.
	 * Also triggers index updates
	 */
	public void checkExternalArchiveChanges(IJavaElement[] elementsToRefresh, IProgressMonitor monitor) throws JavaModelException {
		try {
			for (int i = 0, length = elementsToRefresh.length; i < length; i++) {
				this.addForRefresh(elementsToRefresh[i]);
			}
			boolean hasDelta = this.createExternalArchiveDelta(monitor);
			if (monitor != null && monitor.isCanceled()) return; 
			if (hasDelta){
				// force classpath marker refresh of affected projects
				JavaModel.flushExternalFileCache();
				IJavaElementDelta[] projectDeltas = this.currentDelta.getAffectedChildren();
				for (int i = 0, length = projectDeltas.length; i < length; i++) {
					IJavaElementDelta delta = projectDeltas[i];
					JavaProject javaProject = (JavaProject)delta.getElement();
					javaProject.getResolvedClasspath(
						true/*ignoreUnresolvedEntry*/, 
						true/*generateMarkerOnError*/, 
						false/*don't returnResolutionInProgress*/);
					
					try {
						// touch the project to force it to be recompiled
						javaProject.getProject().touch(monitor);
					} catch (CoreException e) {
						throw new JavaModelException(e);
					}
				}		
				if (this.currentDelta != null) { // if delta has not been fired while creating markers
					this.fire(this.currentDelta, DEFAULT_CHANGE_EVENT);
				}
			}
		} finally {
			this.currentDelta = null;
			if (monitor != null) monitor.done();
		}
	}
	/*
	 * Process the given delta and look for projects being added, opened, closed or
	 * with a java nature being added or removed.
	 * Note that projects being deleted are checked in deleting(IProject).
	 * In all cases, add the project's dependents to the list of projects to update
	 * so that the classpath related markers can be updated.
	 */
	private void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
		IResource resource = delta.getResource();
		boolean processChildren = false;

		switch (resource.getType()) {
			case IResource.ROOT :
				// workaround for bug 15168 circular errors not reported 
				if (this.state.modelProjectsCache == null) {
					try {
						this.state.modelProjectsCache = this.manager.getJavaModel().getJavaProjects();
					} catch (JavaModelException e) {
						// java model doesn't exist: never happens
					}
				}
				processChildren = true;
				break;
			case IResource.PROJECT :
				// NB: No need to check project's nature as if the project is not a java project:
				//     - if the project is added or changed this is a noop for projectsBeingDeleted
				//     - if the project is closed, it has already lost its java nature
				IProject project = (IProject)resource;
				JavaProject javaProject = (JavaProject)JavaCore.create(project);
				switch (delta.getKind()) {
					case IResourceDelta.ADDED :
						this.manager.batchContainerInitializations = true;
					
						// remember project and its dependents
						this.addToRootsToRefreshWithDependents(javaProject);
						
						// workaround for bug 15168 circular errors not reported 
						if (JavaProject.hasJavaNature(project)) {
							this.addToParentInfo(javaProject);
						}
						this.state.rootsAreStale = true; 
						break;
						
					case IResourceDelta.CHANGED : 
							if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
								this.manager.batchContainerInitializations = true;
		
								// project opened or closed: remember  project and its dependents
								this.addToRootsToRefreshWithDependents(javaProject);
								
								// workaround for bug 15168 circular errors not reported 
								if (project.isOpen()) {
									if (JavaProject.hasJavaNature(project)) {
										this.addToParentInfo(javaProject);
									}
								} else {
									try {
										javaProject.close();
									} catch (JavaModelException e) {
										// java project doesn't exist: ignore
									}
									this.removeFromParentInfo(javaProject);
									this.manager.removePerProjectInfo(javaProject);
								}
								this.state.rootsAreStale = true;
							} else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
								boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(project) != null;
								boolean isJavaProject = JavaProject.hasJavaNature(project);
								if (wasJavaProject != isJavaProject) { 
									this.manager.batchContainerInitializations = true;
									
									// java nature added or removed: remember  project and its dependents
									this.addToRootsToRefreshWithDependents(javaProject);
		
									// workaround for bug 15168 circular errors not reported 
									if (isJavaProject) {
										this.addToParentInfo(javaProject);
									} else {
										// remove classpath cache so that initializeRoots() will not consider the project has a classpath
										this.manager.removePerProjectInfo((JavaProject)JavaCore.create(project));
										// close project
										try {
											javaProject.close();
										} catch (JavaModelException e) {
											// java project doesn't exist: ignore
										}
										this.removeFromParentInfo(javaProject);
									}
									this.state.rootsAreStale = true;
								} else {
									// in case the project was removed then added then changed (see bug 19799)
									if (isJavaProject) { // need nature check - 18698
										this.addToParentInfo(javaProject);
										processChildren = true;
									}
								}
							} else {
								// workaround for bug 15168 circular errors not reported 
								// in case the project was removed then added then changed
								if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
									this.addToParentInfo(javaProject);
									processChildren = true;
								}						
							}		
							break;

					case IResourceDelta.REMOVED : 
						this.manager.batchContainerInitializations = true;

						// remove classpath cache so that initializeRoots() will not consider the project has a classpath
						this.manager.removePerProjectInfo((JavaProject)JavaCore.create(resource));
						this.state.rootsAreStale = true;
						break;
				}
				
				// in all cases, refresh the external jars for this project
				addForRefresh(javaProject);
				
				break;
			case IResource.FILE :
				IFile file = (IFile) resource;
				/* classpath file change */
				if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
					this.manager.batchContainerInitializations = true;
					reconcileClasspathFileUpdate(delta, (JavaProject)JavaCore.create(file.getProject()));
					this.state.rootsAreStale = true;
				}
				break;
				
		}
		if (processChildren) {
			IResourceDelta[] children = delta.getAffectedChildren();
			for (int i = 0; i < children.length; i++) {
				checkProjectsBeingAddedOrRemoved(children[i]);
			}
		}
	}
	private void checkSourceAttachmentChange(IResourceDelta delta, IResource res) {
		IPath rootPath = (IPath)this.state.sourceAttachments.get(res.getFullPath());
		if (rootPath != null) {
			RootInfo rootInfo = this.rootInfo(rootPath, delta.getKind());
			if (rootInfo != null) {
				IJavaProject projectOfRoot = rootInfo.project;
				IPackageFragmentRoot root = null;
				try {
					// close the root so that source attachement cache is flushed
					root = projectOfRoot.findPackageFragmentRoot(rootPath);
					if (root != null) {
						root.close();
					}
				} catch (JavaModelException e) {
					// root doesn't exist: ignore
				}
				if (root == null) return;
				switch (delta.getKind()) {
					case IResourceDelta.ADDED:
						currentDelta().sourceAttached(root);
						break;
					case IResourceDelta.CHANGED:
						currentDelta().sourceDetached(root);
						currentDelta().sourceAttached(root);
						break;
					case IResourceDelta.REMOVED:
						currentDelta().sourceDetached(root);
						break;
				}
			} 
		}
	}
	/*
	 * Closes the given element, which removes it from the cache of open elements.
	 */
	private void close(Openable element) {
		try {
			element.close();
		} catch (JavaModelException e) {
			// do nothing
		}
	}
	/*
	 * Generic processing for elements with changed contents:<ul>
	 * <li>The element is closed such that any subsequent accesses will re-open
	 * the element reflecting its new structure.
	 * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
	 * </ul>
	 * Delta argument could be null if processing an external JAR change
	 */
	private void contentChanged(Openable element) {

		boolean isPrimary = false;
		boolean isPrimaryWorkingCopy = false;
		if (element.getElementType() == IJavaElement.COMPILATION_UNIT) {
			CompilationUnit cu = (CompilationUnit)element;
			isPrimary = cu.isPrimary();
			isPrimaryWorkingCopy = isPrimary && cu.isWorkingCopy();
		}
		if (isPrimaryWorkingCopy) {
			// filter out changes to primary compilation unit in working copy mode
			// just report a change to the resource (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59500)
			currentDelta().changed(element, IJavaElementDelta.F_PRIMARY_RESOURCE);
		} else {
			close(element);
			int flags = IJavaElementDelta.F_CONTENT;
			if (element instanceof JarPackageFragmentRoot){
				flags |= IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED;
			}
			if (isPrimary) {
				flags |= IJavaElementDelta.F_PRIMARY_RESOURCE;
			}
			currentDelta().changed(element, flags);
		}
	}
	/*
	 * Creates the openables corresponding to this resource.
	 * Returns null if none was found.
	 */
	private Openable createElement(IResource resource, int elementType, RootInfo rootInfo) {
		if (resource == null) return null;
		
		IPath path = resource.getFullPath();
		IJavaElement element = null;
		switch (elementType) {
			
			case IJavaElement.JAVA_PROJECT:
			
				// note that non-java resources rooted at the project level will also enter this code with
				// an elementType JAVA_PROJECT (see #elementType(...)).
				if (resource instanceof IProject){

					this.popUntilPrefixOf(path);
					
					if (this.currentElement != null 
						&& this.currentElement.getElementType() == IJavaElement.JAVA_PROJECT
						&& ((IJavaProject)this.currentElement).getProject().equals(resource)) {
						return this.currentElement;
					}
					if  (rootInfo != null && rootInfo.project.getProject().equals(resource)){
						element = rootInfo.project;
						break;
					}
					IProject proj = (IProject)resource;
					if (JavaProject.hasJavaNature(proj)) {
						element = JavaCore.create(proj);
					} else {
						// java project may have been been closed or removed (look for
						// element amongst old java project s list).
						element =  (Openable) this.manager.getJavaModel().findJavaProject(proj);
					}
				}
				break;
			case IJavaElement.PACKAGE_FRAGMENT_ROOT:
				element = rootInfo == null ? JavaCore.create(resource) : rootInfo.getPackageFragmentRoot(resource);
				break;
			case IJavaElement.PACKAGE_FRAGMENT:
				if (rootInfo != null) {
					if (rootInfo.project.contains(resource)) {
						PackageFragmentRoot root = (PackageFragmentRoot) rootInfo.getPackageFragmentRoot(null);
						// create package handle
						IPath pkgPath = path.removeFirstSegments(rootInfo.rootPath.segmentCount());
						String[] pkgName = pkgPath.segments();
						element = root.getPackageFragment(pkgName);
					}
				} else {
					// find the element that encloses the resource
					this.popUntilPrefixOf(path);
				
					if (this.currentElement == null) {
						element = JavaCore.create(resource);
					} else {
						// find the root
						PackageFragmentRoot root = this.currentElement.getPackageFragmentRoot();
						if (root == null) {
							element =  JavaCore.create(resource);
						} else if (((JavaProject)root.getJavaProject()).contains(resource)) {
							// create package handle
							IPath pkgPath = path.removeFirstSegments(root.getPath().segmentCount());
							String[] pkgName = pkgPath.segments();
							element = root.getPackageFragment(pkgName);
						}
					}
				}
				break;
			case IJavaElement.COMPILATION_UNIT:
			case IJavaElement.CLASS_FILE:
				// find the element that encloses the resource
				this.popUntilPrefixOf(path);
				
				if (this.currentElement == null) {
					element =  rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
				} else {
					// find the package
					IPackageFragment pkgFragment = null;
					switch (this.currentElement.getElementType()) {
						case IJavaElement.PACKAGE_FRAGMENT_ROOT:
							PackageFragmentRoot root = (PackageFragmentRoot)this.currentElement;
							IPath rootPath = root.getPath();
							IPath pkgPath = path.removeLastSegments(1);
							String[] pkgName = pkgPath.removeFirstSegments(rootPath.segmentCount()).segments();
							pkgFragment = root.getPackageFragment(pkgName);
							break;
						case IJavaElement.PACKAGE_FRAGMENT:
							Openable pkg = this.currentElement;
							if (pkg.getPath().equals(path.removeLastSegments(1))) {
								pkgFragment = (IPackageFragment)pkg;
							} // else case of package x which is a prefix of x.y
							break;
						case IJavaElement.COMPILATION_UNIT:
						case IJavaElement.CLASS_FILE:
							pkgFragment = (IPackageFragment)this.currentElement.getParent();
							break;
					}
					if (pkgFragment == null) {
						element =  rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
					} else {
						if (elementType == IJavaElement.COMPILATION_UNIT) {
							// create compilation unit handle 
							// fileName validation has been done in elementType(IResourceDelta, int, boolean)
							String fileName = path.lastSegment();
							element = pkgFragment.getCompilationUnit(fileName);
						} else {
							// create class file handle
							// fileName validation has been done in elementType(IResourceDelta, int, boolean)
							String fileName = path.lastSegment();
							element = pkgFragment.getClassFile(fileName);
						}
					}
				}
				break;
		}
		if (element == null) return null;
		this.currentElement = (Openable)element;
		return this.currentElement;
	}
	/*
	 * Check if external archives have changed and create the corresponding deltas.
	 * Returns whether at least on delta was created.
	 */
	private boolean createExternalArchiveDelta(IProgressMonitor monitor) {
		
		if (this.refreshedElements == null) return false;
			
		HashMap externalArchivesStatus = new HashMap();
		boolean hasDelta = false;
		
		// find JARs to refresh
		HashSet archivePathsToRefresh = new HashSet();
		Iterator iterator = this.refreshedElements.iterator();
		this.refreshedElements = null; // null out early to avoid concurrent modification exception (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63534)
		while (iterator.hasNext()) {
			IJavaElement element = (IJavaElement)iterator.next();
			switch(element.getElementType()){
				case IJavaElement.PACKAGE_FRAGMENT_ROOT :
					archivePathsToRefresh.add(element.getPath());
					break;
				case IJavaElement.JAVA_PROJECT :
					JavaProject project = (JavaProject) element;
					if (!JavaProject.hasJavaNature(project.getProject())) {
						// project is not accessible or has lost its Java nature
						break;
					}
					IClasspathEntry[] classpath;
					try {
						classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
						for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
							if (classpath[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
								archivePathsToRefresh.add(classpath[j].getPath());
							}
						}
					} catch (JavaModelException e) {
						// project doesn't exist -> ignore
					}
					break;
				case IJavaElement.JAVA_MODEL :
					IJavaProject[] projects;
					try {
						projects = this.manager.getJavaModel().getOldJavaProjectsList();
					} catch (JavaModelException e1) {
						// cannot retrieve old projects list -> ignore
						continue;
					}
					for (int j = 0, projectsLength = projects.length; j < projectsLength; j++){
						project = (JavaProject) projects[j];
						if (!JavaProject.hasJavaNature(project.getProject())) {
							// project is not accessible or has lost its Java nature
							continue;
						}
						try {
							classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
						} catch (JavaModelException e2) {
							// project doesn't exist -> ignore
							continue;
						}
						for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
							if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
								archivePathsToRefresh.add(classpath[k].getPath());
							}
						}
					}
					break;
			}
		}
		
		// perform refresh
		IJavaProject[] projects;
		try {
			projects = this.manager.getJavaModel().getOldJavaProjectsList();
		} catch (JavaModelException e) {
			// cannot retrieve old projects list -> give up
			return false;
		}
		IWorkspaceRoot wksRoot = ResourcesPlugin.getWorkspace().getRoot();
		for (int i = 0, length = projects.length; i < length; i++) {
			
			if (monitor != null && monitor.isCanceled()) break; 
			
			JavaProject project = (JavaProject) projects[i];
			if (!JavaProject.hasJavaNature(project.getProject())) {
				// project is not accessible or has lost its Java nature
				continue;
			}
			IClasspathEntry[] entries;
			try {
				entries = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
			} catch (JavaModelException e1) {
				// project does not exist -> ignore
				continue;
			}
			for (int j = 0; j < entries.length; j++){
				if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
					
					IPath entryPath = entries[j].getPath();
					
					if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
					
					String status = (String)externalArchivesStatus.get(entryPath); 
					if (status == null){
						
						// compute shared status
						Object targetLibrary = JavaModel.getTarget(wksRoot, entryPath, true);
		
						if (targetLibrary == null){ // missing JAR
							if (this.state.externalTimeStamps.remove(entryPath) != null){
								externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
								// the jar was physically removed: remove the index
								this.manager.indexManager.removeIndex(entryPath);
							}
		
						} else if (targetLibrary instanceof File){ // external JAR
		
							File externalFile = (File)targetLibrary;
							
							// check timestamp to figure if JAR has changed in some way
							Long oldTimestamp =(Long) this.state.externalTimeStamps.get(entryPath);
							long newTimeStamp = getTimeStamp(externalFile);
							if (oldTimestamp != null){
		
								if (newTimeStamp == 0){ // file doesn't exist
									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
									this.state.externalTimeStamps.remove(entryPath);
									// remove the index
									this.manager.indexManager.removeIndex(entryPath);
		
								} else if (oldTimestamp.longValue() != newTimeStamp){
									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_CHANGED);
									this.state.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
									// first remove the index so that it is forced to be re-indexed
									this.manager.indexManager.removeIndex(entryPath);
									// then index the jar
									this.manager.indexManager.indexLibrary(entryPath, project.getProject());
								} else {
									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
								}
							} else {
								if (newTimeStamp == 0){ // jar still doesn't exist
									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
								} else {
									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_ADDED);
									this.state.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
									// index the new jar
									this.manager.indexManager.indexLibrary(entryPath, project.getProject());
								}
							}
						} else { // internal JAR
							externalArchivesStatus.put(entryPath, INTERNAL_JAR_IGNORE);
						}
					}
					// according to computed status, generate a delta
					status = (String)externalArchivesStatus.get(entryPath); 
					if (status != null){
						if (status == EXTERNAL_JAR_ADDED){
							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
							if (VERBOSE){
								System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
							} 
							elementAdded(root, null, null);
							hasDelta = true;
						} else if (status == EXTERNAL_JAR_CHANGED) {
							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
							if (VERBOSE){
								System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
							}
							// reset the corresponding project built state, since the builder would miss this change
							this.manager.setLastBuiltState(project.getProject(), null /*no state*/);
							contentChanged(root);
							hasDelta = true;
						} else if (status == EXTERNAL_JAR_REMOVED) {
							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
							if (VERBOSE){
								System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
							}
							elementRemoved(root, null, null);
							hasDelta = true;
						}
					}
				}
			}
		}
		return hasDelta;
	}
	private JavaElementDelta currentDelta() {
		if (this.currentDelta == null) {
			this.currentDelta = new JavaElementDelta(this.manager.getJavaModel());
		}
		return this.currentDelta;
	}
	/*
	 * Note that the project is about to be deleted.
	 */
	private void deleting(IProject project) {
		
		try {
			// discard indexing jobs that belong to this project so that the project can be 
			// deleted without interferences from the index manager
			this.manager.indexManager.discardJobs(project.getName());

			JavaProject javaProject = (JavaProject)JavaCore.create(project);
			
			// remember roots of this project
			if (this.removedRoots == null) {
				this.removedRoots = new HashMap();
			}
			if (javaProject.isOpen()) {
				this.removedRoots.put(javaProject, javaProject.getPackageFragmentRoots());
			} else {
				// compute roots without opening project
				this.removedRoots.put(
					javaProject, 
					javaProject.computePackageFragmentRoots(
						javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/), 
						false,
						null /*no reverse map*/));
			}
			
			javaProject.close();

			// workaround for bug 15168 circular errors not reported
			if (this.state.modelProjectsCache == null) {
				this.state.modelProjectsCache = this.manager.getJavaModel().getJavaProjects();
			}
			this.removeFromParentInfo(javaProject);

			// remove preferences from per project info
			this.manager.resetProjectPreferences(javaProject);	
		} catch (JavaModelException e) {
			// java project doesn't exist: ignore
		}
	}
	/*
	 * Processing for an element that has been added:<ul>
	 * <li>If the element is a project, do nothing, and do not process
	 * children, as when a project is created it does not yet have any
	 * natures - specifically a java nature.
	 * <li>If the elemet is not a project, process it as added (see
	 * <code>basicElementAdded</code>.
	 * </ul>
	 * Delta argument could be null if processing an external JAR change
	 */
	private void elementAdded(Openable element, IResourceDelta delta, RootInfo rootInfo) {
		int elementType = element.getElementType();
		
		if (elementType == IJavaElement.JAVA_PROJECT) {
			// project add is handled by JavaProject.configure() because
			// when a project is created, it does not yet have a java nature
			if (delta != null && JavaProject.hasJavaNature((IProject)delta.getResource())) {
				addToParentInfo(element);
				if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
					Openable movedFromElement = (Openable)element.getJavaModel().getJavaProject(delta.getMovedFromPath().lastSegment());
					currentDelta().movedTo(element, movedFromElement);
				} else {
					currentDelta().added(element);
				}
				this.state.updateRoots(element.getPath(), delta, this);
				
				// refresh pkg fragment roots and caches of the project (and its dependents)
				this.rootsToRefresh.add(element);
				this.projectCachesToReset.add(element);
			}
		} else {			
			if (delta == null || (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) {
				// regular element addition
				if (isPrimaryWorkingCopy(element, elementType) ) {
					// filter out changes to primary compilation unit in working copy mode
					// just report a change to the resource (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59500)
					currentDelta().changed(element, IJavaElementDelta.F_PRIMARY_RESOURCE);
				} else {
					addToParentInfo(element);
					
					// Force the element to be closed as it might have been opened 
					// before the resource modification came in and it might have a new child
					// For example, in an IWorkspaceRunnable:
					// 1. create a package fragment p using a java model operation
					// 2. open package p
					// 3. add file X.java in folder p
					// When the resource delta comes in, only the addition of p is notified, 
					// but the package p is already opened, thus its children are not recomputed
					// and it appears empty.
					close(element);
			
					currentDelta().added(element);
				}
			} else {
				// element is moved
				addToParentInfo(element);
				close(element);
			
				IPath movedFromPath = delta.getMovedFromPath();
				IResource res = delta.getResource();
				IResource movedFromRes;
				if (res instanceof IFile) {
					movedFromRes = res.getWorkspace().getRoot().getFile(movedFromPath);
				} else {
					movedFromRes = res.getWorkspace().getRoot().getFolder(movedFromPath);
				}
				
				// find the element type of the moved from element
				RootInfo movedFromInfo = this.enclosingRootInfo(movedFromPath, IResourceDelta.REMOVED);
				int movedFromType = 
					this.elementType(
						movedFromRes, 
						IResourceDelta.REMOVED,
						element.getParent().getElementType(), 
						movedFromInfo);
				
				// reset current element as it might be inside a nested root (popUntilPrefixOf() may use the outer root)
				this.currentElement = null;
			
				// create the moved from element
				Openable movedFromElement = 
					elementType != IJavaElement.JAVA_PROJECT && movedFromType == IJavaElement.JAVA_PROJECT ? 
						null : // outside classpath
						this.createElement(movedFromRes, movedFromType, movedFromInfo);
				if (movedFromElement == null) {
					// moved from outside classpath
					currentDelta().added(element);
				} else {
					currentDelta().movedTo(element, movedFromElement);
				}
			}
			
			switch (elementType) {
				case IJavaElement.PACKAGE_FRAGMENT_ROOT :
					// when a root is added, and is on the classpath, the project must be updated
					JavaProject project = (JavaProject) element.getJavaProject();

					// refresh pkg fragment roots and caches of the project (and its dependents)
					this.rootsToRefresh.add(project);
					this.projectCachesToReset.add(project);
					
					break;
				case IJavaElement.PACKAGE_FRAGMENT :
					// reset project's package fragment cache 
					project = (JavaProject) element.getJavaProject();
					this.projectCachesToReset.add(project);						

					break;
			}
		}
	}
	/*
	 * Generic processing for a removed element:<ul>
	 * <li>Close the element, removing its structure from the cache
	 * <li>Remove the element from its parent's cache of children
	 * <li>Add a REMOVED entry in the delta
	 * </ul>
	 * Delta argument could be null if processing an external JAR change
	 */
	private void elementRemoved(Openable element, IResourceDelta delta, RootInfo rootInfo) {
		
		int elementType = element.getElementType();
		if (delta == null || (delta.getFlags() & IResourceDelta.MOVED_TO) == 0) {
			// regular element removal
			if (isPrimaryWorkingCopy(element, elementType) ) {
				// filter out changes to primary compilation unit in working copy mode
				// just report a change to the resource (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59500)
				currentDelta().changed(element, IJavaElementDelta.F_PRIMARY_RESOURCE);
			} else {
				close(element);
				removeFromParentInfo(element);
				currentDelta().removed(element);
			}
		} else {
			// element is moved
			close(element);
			removeFromParentInfo(element);
			IPath movedToPath = delta.getMovedToPath();
			IResource res = delta.getResource();
			IResource movedToRes;
			switch (res.getType()) {
				case IResource.PROJECT:
					movedToRes = res.getWorkspace().getRoot().getProject(movedToPath.lastSegment());
					break;
				case IResource.FOLDER:
					movedToRes = res.getWorkspace().getRoot().getFolder(movedToPath);
					break;
				case IResource.FILE:
					movedToRes = res.getWorkspace().getRoot().getFile(movedToPath);
					break;
				default:
					return;
			}

			// find the element type of the moved from element
			RootInfo movedToInfo = this.enclosingRootInfo(movedToPath, IResourceDelta.ADDED);
			int movedToType = 
				this.elementType(
					movedToRes, 
					IResourceDelta.ADDED,
					element.getParent().getElementType(), 
					movedToInfo);

			// reset current element as it might be inside a nested root (popUntilPrefixOf() may use the outer root)
			this.currentElement = null;
			
			// create the moved To element
			Openable movedToElement = 
				elementType != IJavaElement.JAVA_PROJECT && movedToType == IJavaElement.JAVA_PROJECT ? 
					null : // outside classpath
					this.createElement(movedToRes, movedToType, movedToInfo);
			if (movedToElement == null) {
				// moved outside classpath
				currentDelta().removed(element);
			} else {
				currentDelta().movedFrom(element, movedToElement);
			}
		}

		switch (elementType) {
			case IJavaElement.JAVA_MODEL :
				this.manager.indexManager.reset();
				break;
			case IJavaElement.JAVA_PROJECT :
				this.state.updateRoots(element.getPath(), delta, this);

				// refresh pkg fragment roots and caches of the project (and its dependents)
				this.rootsToRefresh.add(element);
				this.projectCachesToReset.add(element);

				break;
			case IJavaElement.PACKAGE_FRAGMENT_ROOT :
				JavaProject project = (JavaProject) element.getJavaProject();

				// refresh pkg fragment roots and caches of the project (and its dependents)
				this.rootsToRefresh.add(project);
				this.projectCachesToReset.add(project);				

				break;
			case IJavaElement.PACKAGE_FRAGMENT :
				// reset package fragment cache
				project = (JavaProject) element.getJavaProject();
				this.projectCachesToReset.add(project);

				break;
		}
	}
	/*
	 * Returns the type of the java element the given delta matches to.
	 * Returns NON_JAVA_RESOURCE if unknown (e.g. a non-java resource or excluded .java file)
	 */
	private int elementType(IResource res, int kind, int parentType, RootInfo rootInfo) {
		switch (parentType) {
			case IJavaElement.JAVA_MODEL:
				// case of a movedTo or movedFrom project (other cases are handled in processResourceDelta(...)
				return IJavaElement.JAVA_PROJECT;
			
			case NON_JAVA_RESOURCE:
			case IJavaElement.JAVA_PROJECT:
				if (rootInfo == null) {
					rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
				}
				if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
					return IJavaElement.PACKAGE_FRAGMENT_ROOT;
				} 
				// not yet in a package fragment root or root of another project
				// or package fragment to be included (see below)
				// -> let it go through

			case IJavaElement.PACKAGE_FRAGMENT_ROOT:
			case IJavaElement.PACKAGE_FRAGMENT:
				if (rootInfo == null) {
					rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
				}
				if (rootInfo == null) {
					return NON_JAVA_RESOURCE;
				}
				if (Util.isExcluded(res, rootInfo.inclusionPatterns, rootInfo.exclusionPatterns)) {
					return NON_JAVA_RESOURCE;
				}
				if (res.getType() == IResource.FOLDER) {
					if (Util.isValidFolderNameForPackage(res.getName())) {
						return IJavaElement.PACKAGE_FRAGMENT;
					}
					return NON_JAVA_RESOURCE;
				}
				String fileName = res.getName();
				if (Util.isValidCompilationUnitName(fileName)) {
					return IJavaElement.COMPILATION_UNIT;
				} else if (Util.isValidClassFileName(fileName)) {
					return IJavaElement.CLASS_FILE;
				} else if (this.rootInfo(res.getFullPath(), kind) != null) {
					// case of proj=src=bin and resource is a jar file on the classpath
					return IJavaElement.PACKAGE_FRAGMENT_ROOT;
				} else {
					return NON_JAVA_RESOURCE;
				}
				
			default:
				return NON_JAVA_RESOURCE;
		}
	}
	/*
	 * Flushes all deltas without firing them.
	 */
	public void flush() {
		this.javaModelDeltas = new ArrayList();
	}
	/*
	 * Finds the root info this path is included in.
	 * Returns null if not found.
	 */
	private RootInfo enclosingRootInfo(IPath path, int kind) {
		while (path != null && path.segmentCount() > 0) {
			RootInfo rootInfo =  this.rootInfo(path, kind);
			if (rootInfo != null) return rootInfo;
			path = path.removeLastSegments(1);
		}
		return null;
	}
	/*
	 * Fire Java Model delta, flushing them after the fact after post_change notification.
	 * If the firing mode has been turned off, this has no effect. 
	 */
	public void fire(IJavaElementDelta customDelta, int eventType) {
		if (!this.isFiring) return;
		
		if (DEBUG) {
			System.out.println("-----------------------------------------------------------------------------------------------------------------------");//$NON-NLS-1$
		}

		IJavaElementDelta deltaToNotify;
		if (customDelta == null){
			deltaToNotify = this.mergeDeltas(this.javaModelDeltas);
		} else {
			deltaToNotify = customDelta;
		}
			
		// Refresh internal scopes
		if (deltaToNotify != null) {
			Iterator scopes = this.manager.searchScopes.keySet().iterator();
			while (scopes.hasNext()) {
				AbstractSearchScope scope = (AbstractSearchScope)scopes.next();
				scope.processDelta(deltaToNotify);
			}
		}
			
		// Notification
	
		// Important: if any listener reacts to notification by updating the listeners list or mask, these lists will
		// be duplicated, so it is necessary to remember original lists in a variable (since field values may change under us)
		IElementChangedListener[] listeners = this.state.elementChangedListeners;
		int[] listenerMask = this.state.elementChangedListenerMasks;
		int listenerCount = this.state.elementChangedListenerCount;

		switch (eventType) {
			case DEFAULT_CHANGE_EVENT:
				firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount);
				fireReconcileDelta(listeners, listenerMask, listenerCount);
				break;
			case ElementChangedEvent.POST_CHANGE:
				firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount);
				fireReconcileDelta(listeners, listenerMask, listenerCount);
				break;
		}
	}

	private void firePostChangeDelta(
		IJavaElementDelta deltaToNotify,
		IElementChangedListener[] listeners,
		int[] listenerMask,
		int listenerCount) {
			
		// post change deltas
		if (DEBUG){
			System.out.println("FIRING POST_CHANGE Delta ["+Thread.currentThread()+"]:"); //$NON-NLS-1$//$NON-NLS-2$
			System.out.println(deltaToNotify == null ? "<NONE>" : deltaToNotify.toString()); //$NON-NLS-1$
		}
		if (deltaToNotify != null) {
			// flush now so as to keep listener reactions to post their own deltas for subsequent iteration
			this.flush();
			
			notifyListeners(deltaToNotify, ElementChangedEvent.POST_CHANGE, listeners, listenerMask, listenerCount);
		} 
	}		
	private void fireReconcileDelta(
		IElementChangedListener[] listeners,
		int[] listenerMask,
		int listenerCount) {


		IJavaElementDelta deltaToNotify = mergeDeltas(this.reconcileDeltas.values());
		if (DEBUG){
			System.out.println("FIRING POST_RECONCILE Delta ["+Thread.currentThread()+"]:"); //$NON-NLS-1$//$NON-NLS-2$
			System.out.println(deltaToNotify == null ? "<NONE>" : deltaToNotify.toString()); //$NON-NLS-1$
		}
		if (deltaToNotify != null) {
			// flush now so as to keep listener reactions to post their own deltas for subsequent iteration
			this.reconcileDeltas = new HashMap();
		
			notifyListeners(deltaToNotify, ElementChangedEvent.POST_RECONCILE, listeners, listenerMask, listenerCount);
		} 
	}
	/*
	 * Returns whether a given delta contains some information relevant to the JavaModel,
	 * in particular it will not consider SYNC or MARKER only deltas.
	 */
	private boolean isAffectedBy(IResourceDelta rootDelta){
		//if (rootDelta == null) System.out.println("NULL DELTA");
		//long start = System.currentTimeMillis();
		if (rootDelta != null) {
			// use local exception to quickly escape from delta traversal
			class FoundRelevantDeltaException extends RuntimeException {
				private static final long serialVersionUID = 7137113252936111022L; // backward compatible
				// only the class name is used (to differenciate from other RuntimeExceptions)
			}
			try {
				rootDelta.accept(new IResourceDeltaVisitor() {
					public boolean visit(IResourceDelta delta) /* throws CoreException */ {
						switch (delta.getKind()){
							case IResourceDelta.ADDED :
							case IResourceDelta.REMOVED :
								throw new FoundRelevantDeltaException();
							case IResourceDelta.CHANGED :
								// if any flag is set but SYNC or MARKER, this delta should be considered
								if (delta.getAffectedChildren().length == 0 // only check leaf delta nodes
										&& (delta.getFlags() & ~(IResourceDelta.SYNC | IResourceDelta.MARKERS)) != 0) {
									throw new FoundRelevantDeltaException();
								}
						}
						return true;
					}
				});
			} catch(FoundRelevantDeltaException e) {
				//System.out.println("RELEVANT DELTA detected in: "+ (System.currentTimeMillis() - start));
				return true;
			} catch(CoreException e) { // ignore delta if not able to traverse
			}
		}
		//System.out.println("IGNORE SYNC DELTA took: "+ (System.currentTimeMillis() - start));
		return false;
	}
	/*
	 * Returns whether the given element is a primary compilation unit in working copy mode.
	 */
	private boolean isPrimaryWorkingCopy(IJavaElement element, int elementType) {
		if (elementType == IJavaElement.COMPILATION_UNIT) {
			CompilationUnit cu = (CompilationUnit)element;
			return cu.isPrimary() && cu.isWorkingCopy();
		}
		return false;
	}
	/*
	 * Returns whether the given resource is in one of the given output folders and if
	 * it is filtered out from this output folder.
	 */
	private boolean isResFilteredFromOutput(OutputsInfo info, IResource res, int elementType) {
		if (info != null) {
			IPath resPath = res.getFullPath();
			for (int i = 0;  i < info.outputCount; i++) {
				if (info.paths[i].isPrefixOf(resPath)) {
					if (info.traverseModes[i] != IGNORE) {
						// case of bin=src
						if (info.traverseModes[i] == SOURCE && elementType == IJavaElement.CLASS_FILE) {
							return true;
						}
						// case of .class file under project and no source folder
						// proj=bin
						if (elementType == IJavaElement.JAVA_PROJECT 
								&& res instanceof IFile 
								&& Util.isValidClassFileName(res.getName())) {
							return true;
						}
					} else {
						return true;
					}
				}
			}
		}
		return false;
	}
	/*
	 * Merges all awaiting deltas.
	 */
	private IJavaElementDelta mergeDeltas(Collection deltas) {
		if (deltas.size() == 0) return null;
		if (deltas.size() == 1) return (IJavaElementDelta)deltas.iterator().next();
		
		if (VERBOSE) {
			System.out.println("MERGING " + deltas.size() + " DELTAS ["+Thread.currentThread()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		
		Iterator iterator = deltas.iterator();
		JavaElementDelta rootDelta = new JavaElementDelta(this.manager.javaModel);
		boolean insertedTree = false;
		while (iterator.hasNext()) {
			JavaElementDelta delta = (JavaElementDelta)iterator.next();
			if (VERBOSE) {
				System.out.println(delta.toString());
			}
			IJavaElement element = delta.getElement();
			if (this.manager.javaModel.equals(element)) {
				IJavaElementDelta[] children = delta.getAffectedChildren();
				for (int j = 0; j < children.length; j++) {
					JavaElementDelta projectDelta = (JavaElementDelta) children[j];
					rootDelta.insertDeltaTree(projectDelta.getElement(), projectDelta);
					insertedTree = true;
				}
				IResourceDelta[] resourceDeltas = delta.getResourceDeltas();
				if (resourceDeltas != null) {
					for (int i = 0, length = resourceDeltas.length; i < length; i++) {
						rootDelta.addResourceDelta(resourceDeltas[i]);
						insertedTree = true;
					}
				}
			} else {
				rootDelta.insertDeltaTree(element, delta);
				insertedTree = true;
			}
		}
		if (insertedTree) return rootDelta;
		return null;
	}	
	private void notifyListeners(IJavaElementDelta deltaToNotify, int eventType, IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) {
		final ElementChangedEvent extraEvent = new ElementChangedEvent(deltaToNotify, eventType);
		for (int i= 0; i < listenerCount; i++) {
			if ((listenerMask[i] & eventType) != 0){
				final IElementChangedListener listener = listeners[i];
				long start = -1;
				if (VERBOSE) {
					System.out.print("Listener #" + (i+1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$
					start = System.currentTimeMillis();
				}
				// wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
				Platform.run(new ISafeRunnable() {
					public void handleException(Throwable exception) {
						Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
					}
					public void run() throws Exception {
						listener.elementChanged(extraEvent);
					}
				});
				if (VERBOSE) {
					System.out.println(" -> " + (System.currentTimeMillis()-start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
		}
	}
	private void notifyTypeHierarchies(IElementChangedListener[] listeners, int listenerCount) {
		for (int i= 0; i < listenerCount; i++) {
			final IElementChangedListener listener = listeners[i];
			if (!(listener instanceof TypeHierarchy)) continue;

			// wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
			Platform.run(new ISafeRunnable() {
				public void handleException(Throwable exception) {
					Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
				}
				public void run() throws Exception {
					TypeHierarchy typeHierarchy = (TypeHierarchy)listener;
					if (typeHierarchy.hasFineGrainChanges()) {
						// case of changes in primary working copies
						typeHierarchy.needsRefresh = true;
						typeHierarchy.fireChange();
					}
				}
			});
		}
	}
	/*
	 * Generic processing for elements with changed contents:<ul>
	 * <li>The element is closed such that any subsequent accesses will re-open
	 * the element reflecting its new structure.
	 * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
	 * </ul>
	 */
	private void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
		throws JavaModelException {

		// reset non-java resources if element was open
		if (element.isOpen()) {
			JavaElementInfo info = (JavaElementInfo)element.getElementInfo();
			switch (element.getElementType()) {
				case IJavaElement.JAVA_MODEL :
					((JavaModelInfo) info).nonJavaResources = null;
					currentDelta().addResourceDelta(delta);
					return;
				case IJavaElement.JAVA_PROJECT :
					((JavaProjectElementInfo) info).setNonJavaResources(null);
	
					// if a package fragment root is the project, clear it too
					JavaProject project = (JavaProject) element;
					PackageFragmentRoot projectRoot =
						(PackageFragmentRoot) project.getPackageFragmentRoot(project.getProject());
					if (projectRoot.isOpen()) {
						((PackageFragmentRootInfo) projectRoot.getElementInfo()).setNonJavaResources(
							null);
					}
					break;
				case IJavaElement.PACKAGE_FRAGMENT :
					 ((PackageFragmentInfo) info).setNonJavaResources(null);
					break;
				case IJavaElement.PACKAGE_FRAGMENT_ROOT :
					 ((PackageFragmentRootInfo) info).setNonJavaResources(null);
			}
		}

		JavaElementDelta current = currentDelta();
		JavaElementDelta elementDelta = current.find(element);
		if (elementDelta == null) {
			// don't use find after creating the delta as it can be null (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63434)
			elementDelta = current.changed(element, IJavaElementDelta.F_CONTENT);
		}
		elementDelta.addResourceDelta(delta);
	}
	/*
	 * Returns the other root infos for the given path. Look in the old other roots table if kind is REMOVED.
	 */
	private ArrayList otherRootsInfo(IPath path, int kind) {
		if (kind == IResourceDelta.REMOVED) {
			return (ArrayList)this.state.oldOtherRoots.get(path);
		}
		return (ArrayList)this.state.otherRoots.get(path);
	}	
	
	private OutputsInfo outputsInfo(RootInfo rootInfo, IResource res) {
		try {
			JavaProject proj =
				rootInfo == null ?
					(JavaProject)this.createElement(res.getProject(), IJavaElement.JAVA_PROJECT, null) :
					rootInfo.project;
			if (proj != null) {
				IPath projectOutput = proj.getOutputLocation();
				int traverseMode = IGNORE;
				if (proj.getProject().getFullPath().equals(projectOutput)){ // case of proj==bin==src
					return new OutputsInfo(new IPath[] {projectOutput}, new int[] {SOURCE}, 1);
				} 
				IClasspathEntry[] classpath = proj.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
				IPath[] outputs = new IPath[classpath.length+1];
				int[] traverseModes = new int[classpath.length+1];
				int outputCount = 1;
				outputs[0] = projectOutput;
				traverseModes[0] = traverseMode;
				for (int i = 0, length = classpath.length; i < length; i++) {
					IClasspathEntry entry = classpath[i];
					IPath entryPath = entry.getPath();
					IPath output = entry.getOutputLocation();
					if (output != null) {
						outputs[outputCount] = output;
						// check case of src==bin
						if (entryPath.equals(output)) {
							traverseModes[outputCount++] = (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) ? SOURCE : BINARY;
						} else {
							traverseModes[outputCount++] = IGNORE;
						}
					}
					
					// check case of src==bin
					if (entryPath.equals(projectOutput)) {
						traverseModes[0] = (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) ? SOURCE : BINARY;
					}
				}
				return new OutputsInfo(outputs, traverseModes, outputCount);
			}
		} catch (JavaModelException e) {
			// java project doesn't exist: ignore
		}
		return null;
	}
	private void popUntilPrefixOf(IPath path) {
		while (this.currentElement != null) {
			IPath currentElementPath = null;
			if (this.currentElement instanceof IPackageFragmentRoot) {
				currentElementPath = ((IPackageFragmentRoot)this.currentElement).getPath();
			} else {
				IResource currentElementResource = this.currentElement.getResource();
				if (currentElementResource != null) {
					currentElementPath = currentElementResource.getFullPath();
				}
			}
			if (currentElementPath != null) {
				if (this.currentElement instanceof IPackageFragment 
					&& ((IPackageFragment) this.currentElement).isDefaultPackage()
					&& currentElementPath.segmentCount() != path.segmentCount()-1) {
						// default package and path is not a direct child
						this.currentElement = (Openable)this.currentElement.getParent();
				}
				if (currentElementPath.isPrefixOf(path)) {
					return;
				}
			}
			this.currentElement = (Openable)this.currentElement.getParent();
		}
	}
	/*
	 * Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code> into
	 * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
	 * relevant <code>JavaModel</code>s.
	 */
	private IJavaElementDelta processResourceDelta(IResourceDelta changes) {

		try {
			IJavaModel model = this.manager.getJavaModel();
			if (!model.isOpen()) {
				// force opening of java model so that java element delta are reported
				try {
					model.open(null);
				} catch (JavaModelException e) {
					if (VERBOSE) {
						e.printStackTrace();
					}
					return null;
				}
			}
			this.state.initializeRoots();
			this.currentElement = null;
			
			// get the workspace delta, and start processing there.
			IResourceDelta[] deltas = changes.getAffectedChildren();
			for (int i = 0; i < deltas.length; i++) {
				IResourceDelta delta = deltas[i];
				IResource res = delta.getResource();
				
				// find out the element type
				RootInfo rootInfo = null;
				int elementType;
				IProject proj = (IProject)res;
				boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(proj) != null;
				boolean isJavaProject = JavaProject.hasJavaNature(proj);
				if (!wasJavaProject && !isJavaProject) {
					elementType = NON_JAVA_RESOURCE;
				} else {
					rootInfo = this.enclosingRootInfo(res.getFullPath(), delta.getKind());
					if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
						elementType = IJavaElement.PACKAGE_FRAGMENT_ROOT;
					} else {
						elementType = IJavaElement.JAVA_PROJECT; 
					}
				}
				
				// traverse delta
				this.traverseDelta(delta, elementType, rootInfo, null);
				
				if (elementType == NON_JAVA_RESOURCE
						|| (wasJavaProject != isJavaProject && (delta.getKind()) == IResourceDelta.CHANGED)) { // project has changed nature (description or open/closed)
					try {
						// add child as non java resource
						nonJavaResourcesChanged((JavaModel)model, delta);
					} catch (JavaModelException e) {
						// java model could not be opened
					}
				}

			}
			refreshPackageFragmentRoots();
			resetProjectCaches();

			return this.currentDelta;
		} finally {
			this.currentDelta = null;
			this.rootsToRefresh.clear();
			this.projectCachesToReset.clear();
		}
	}
	/*
	 * Update the JavaModel according to a .classpath file change. The file can have changed as a result of a previous
	 * call to JavaProject#setRawClasspath or as a result of some user update (through repository)
	 */
	private void reconcileClasspathFileUpdate(IResourceDelta delta, JavaProject project) {

		switch (delta.getKind()) {
			case IResourceDelta.REMOVED : // recreate one based on in-memory classpath
//				try {
//					JavaModelManager.PerProjectInfo info = project.getPerProjectInfo();
//					if (info.rawClasspath != null) { // if there is an in-memory classpath
//						project.saveClasspath(info.rawClasspath, info.outputLocation);
//					}
//				} catch (JavaModelException e) {
//					if (project.getProject().isAccessible()) {
//						Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
//					}
//				}
				break;
			case IResourceDelta.CHANGED :
				int flags = delta.getFlags();
				if ((flags & IResourceDelta.CONTENT) == 0  // only consider content change
					&& (flags & IResourceDelta.ENCODING) == 0 // and encoding change
					&& (flags & IResourceDelta.MOVED_FROM) == 0) {// and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
					break;
				}
			// fall through
			case IResourceDelta.ADDED :
				try {
					project.forceClasspathReload(null);
				} catch (RuntimeException e) {
					if (VERBOSE) {
						e.printStackTrace();
					}
				} catch (JavaModelException e) {	
					if (VERBOSE) {
						e.printStackTrace();
					}
				}
		}
	}

	/*
	 * Traverse the set of projects which have changed namespace, and reset their 
	 * caches and their dependents
	 */
	private void resetProjectCaches() {
		Iterator iterator = this.projectCachesToReset.iterator();
		HashSet affectedDependents = new HashSet();
		while (iterator.hasNext()) {
			JavaProject project = (JavaProject)iterator.next();
			project.resetCaches();
			addDependentProjects(project.getPath(), affectedDependents);
		}
		// reset caches of dependent projects
		iterator = affectedDependents.iterator();
		while (iterator.hasNext()) {
			JavaProject project = (JavaProject) iterator.next();
			project.resetCaches();
		}
	}
	/* 
	 * Refresh package fragment roots of projects that were affected
	 */
	private void refreshPackageFragmentRoots() {
		Iterator iterator = this.rootsToRefresh.iterator();
		while (iterator.hasNext()) {
			JavaProject project = (JavaProject)iterator.next();
			project.updatePackageFragmentRoots();
		}
	}
	/*
	 * Registers the given delta with this delta processor.
	 */
	public void registerJavaModelDelta(IJavaElementDelta delta) {
		this.javaModelDeltas.add(delta);
	}
	/*
	 * Removes the given element from its parents cache of children. If the
	 * element does not have a parent, or the parent is not currently open,
	 * this has no effect. 
	 */
	private void removeFromParentInfo(Openable child) {

		Openable parent = (Openable) child.getParent();
		if (parent != null && parent.isOpen()) {
			try {
				JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
				info.removeChild(child);
			} catch (JavaModelException e) {
				// do nothing - we already checked if open
			}
		}
	}
	/*
	 * Notification that some resource changes have happened
	 * on the platform, and that the Java Model should update any required
	 * internal structures such that its elements remain consistent.
	 * Translates <code>IResourceDeltas</code> into <code>IJavaElementDeltas</code>.
	 *
	 * @see IResourceDelta
	 * @see IResource 
	 */
	public void resourceChanged(IResourceChangeEvent event) {
	
		if (event.getSource() instanceof IWorkspace) {
			int eventType = this.overridenEventType == -1 ? event.getType() : this.overridenEventType;
			IResource resource = event.getResource();
			IResourceDelta delta = event.getDelta();
			
			switch(eventType){
				case IResourceChangeEvent.PRE_DELETE :
					try {
						if(resource.getType() == IResource.PROJECT 
							&& ((IProject) resource).hasNature(JavaCore.NATURE_ID)) {
								
							deleting((IProject)resource);
						}
					} catch(CoreException e){
						// project doesn't exist or is not open: ignore
					}
					return;
					
				case IResourceChangeEvent.POST_CHANGE :
					if (isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
						try {
							try {
								stopDeltas();
								checkProjectsBeingAddedOrRemoved(delta);
								if (this.refreshedElements != null) {
									createExternalArchiveDelta(null);
								}
								IJavaElementDelta translatedDelta = processResourceDelta(delta);
								if (translatedDelta != null) { 
									registerJavaModelDelta(translatedDelta);
								}
							} finally {
								startDeltas();
							}
							notifyTypeHierarchies(this.state.elementChangedListeners, this.state.elementChangedListenerCount);
							fire(null, ElementChangedEvent.POST_CHANGE);
						} finally {
							// workaround for bug 15168 circular errors not reported 
							this.state.modelProjectsCache = null;
							this.removedRoots = null;
						}
					}
					return;
					
				case IResourceChangeEvent.PRE_BUILD :
				    DeltaProcessingState.ProjectUpdateInfo[] updates = this.state.removeAllProjectUpdates();
					if (updates != null) {
					    for (int i = 0, length = updates.length; i < length; i++) {
					        try {
						        updates[i].updateProjectReferencesIfNecessary();
					        } catch(JavaModelException e) {
					            // do nothing
					        }
					    }
					}
					// this.processPostChange = false;
					if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
						updateClasspathMarkers(delta);
						JavaBuilder.buildStarting();
					}
					// does not fire any deltas
					return;

				case IResourceChangeEvent.POST_BUILD :
					JavaBuilder.buildFinished();
					return;
			}
		}
	}
	/*
	 * Returns the root info for the given path. Look in the old roots table if kind is REMOVED.
	 */
	private RootInfo rootInfo(IPath path, int kind) {
		if (kind == IResourceDelta.REMOVED) {
			return (RootInfo)this.state.oldRoots.get(path);
		}
		return (RootInfo)this.state.roots.get(path);
	}
	/*
	 * Turns the firing mode to on. That is, deltas that are/have been
	 * registered will be fired.
	 */
	private void startDeltas() {
		this.isFiring= true;
	}
	/*
	 * Turns the firing mode to off. That is, deltas that are/have been
	 * registered will not be fired until deltas are started again.
	 */
	private void stopDeltas() {
		this.isFiring= false;
	}
	/*
	 * Converts an <code>IResourceDelta</code> and its children into
	 * the corresponding <code>IJavaElementDelta</code>s.
	 */
	private void traverseDelta(
		IResourceDelta delta, 
		int elementType, 
		RootInfo rootInfo,
		OutputsInfo outputsInfo) {
			
		IResource res = delta.getResource();
	
		// set stack of elements
		if (this.currentElement == null && rootInfo != null) {
			this.currentElement = rootInfo.project;
		}
		
		// process current delta
		boolean processChildren = true;
		if (res instanceof IProject) {
			processChildren = 
				this.updateCurrentDeltaAndIndex(
					delta, 
					elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT ? 
						IJavaElement.JAVA_PROJECT : // case of prj=src
						elementType, 
					rootInfo);
		} else if (rootInfo != null) {
			processChildren = this.updateCurrentDeltaAndIndex(delta, elementType, rootInfo);
		} else {
			// not yet inside a package fragment root
			processChildren = true;
		}
		
		// get the project's output locations and traverse mode
		if (outputsInfo == null) outputsInfo = this.outputsInfo(rootInfo, res);
	
		// process children if needed
		if (processChildren) {
			IResourceDelta[] children = delta.getAffectedChildren();
			boolean oneChildOnClasspath = false;
			int length = children.length;
			IResourceDelta[] orphanChildren = null;
			Openable parent = null;
			boolean isValidParent = true;
			for (int i = 0; i < length; i++) {
				IResourceDelta child = children[i];
				IResource childRes = child.getResource();
	
				// check source attachment change
				this.checkSourceAttachmentChange(child, childRes);
				
				// find out whether the child is a package fragment root of the current project
				IPath childPath = childRes.getFullPath();
				int childKind = child.getKind();
				RootInfo childRootInfo = this.rootInfo(childPath, childKind);
				if (childRootInfo != null && !childRootInfo.isRootOfProject(childPath)) {
					// package fragment root of another project (dealt with later)
					childRootInfo = null;
				}
				
				// compute child type
				int childType = 
					this.elementType(
						childRes, 
						childKind,
						elementType, 
						rootInfo == null ? childRootInfo : rootInfo
					);
						
				// is childRes in the output folder and is it filtered out ?
				boolean isResFilteredFromOutput = this.isResFilteredFromOutput(outputsInfo, childRes, childType);

				boolean isNestedRoot = rootInfo != null && childRootInfo != null;
				if (!isResFilteredFromOutput 
						&& !isNestedRoot) { // do not treat as non-java rsc if nested root

					this.traverseDelta(child, childType, rootInfo == null ? childRootInfo : rootInfo, outputsInfo); // traverse delta for child in the same project

					if (childType == NON_JAVA_RESOURCE) {
						if (rootInfo != null) { // if inside a package fragment root
							if (!isValidParent) continue; 
							if (parent == null) {
								// find the parent of the non-java resource to attach to
								if (this.currentElement == null
										|| !rootInfo.project.equals(this.currentElement.getJavaProject())) { // note if currentElement is the IJavaModel, getJavaProject() is null
									// force the currentProject to be used
									this.currentElement = rootInfo.project;
								}
								if (elementType == IJavaElement.JAVA_PROJECT
									|| (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT 
										&& res instanceof IProject)) { 
									// NB: attach non-java resource to project (not to its package fragment root)
									parent = rootInfo.project;
								} else {
									parent = this.createElement(res, elementType, rootInfo);
								}
								if (parent == null) {
									isValidParent = false;
									continue;
								}
							}
							// add child as non java resource
							try {
								nonJavaResourcesChanged(parent, child);
							} catch (JavaModelException e) {
								// ignore
							}
						} else {
							// the non-java resource (or its parent folder) will be attached to the java project
							if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
							orphanChildren[i] = child;
						}
					} else {
						oneChildOnClasspath = true;
					}
				} else {
					oneChildOnClasspath = true; // to avoid reporting child delta as non-java resource delta
				}
								
				// if child is a nested root 
				// or if it is not a package fragment root of the current project
				// but it is a package fragment root of another project, traverse delta too
				if (isNestedRoot 
						|| (childRootInfo == null && (childRootInfo = this.rootInfo(childPath, childKind)) != null)) {
					this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
				}
	
				// if the child is a package fragment root of one or several other projects
				ArrayList rootList;
				if ((rootList = this.otherRootsInfo(childPath, childKind)) != null) {
					Iterator iterator = rootList.iterator();
					while (iterator.hasNext()) {
						childRootInfo = (RootInfo) iterator.next();
						this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
					}
				}
			}
			if (orphanChildren != null
					&& (oneChildOnClasspath // orphan children are siblings of a package fragment root
						|| res instanceof IProject)) { // non-java resource directly under a project
						
				// attach orphan children
				IProject rscProject = res.getProject();
				JavaProject adoptiveProject = (JavaProject)JavaCore.create(rscProject);
				if (adoptiveProject != null 
						&& JavaProject.hasJavaNature(rscProject)) { // delta iff Java project (18698)
					for (int i = 0; i < length; i++) {
						if (orphanChildren[i] != null) {
							try {
								nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
							} catch (JavaModelException e) {
								// ignore
							}
						}
					}
				}
			} // else resource delta will be added by parent
		} // else resource delta will be added by parent
	}

	/*
	 * Check whether .classpath files are affected by the given delta.
	 * Creates/removes problem markers if needed.
	 * Remember the affected projects in the given set.
	 */
	private void updateClasspathMarkers(IResourceDelta delta, HashSet affectedProjects, Map preferredClasspaths, Map preferredOutputs) {
		IResource resource = delta.getResource();
		boolean processChildren = false;

		switch (resource.getType()) {
	
			case IResource.ROOT :
				if (delta.getKind() == IResourceDelta.CHANGED) {
					processChildren = true;
				}
				break;
			case IResource.PROJECT :
				IProject project = (IProject)resource;
				int kind = delta.getKind();
				boolean isJavaProject = JavaProject.hasJavaNature(project);
				switch (kind) {
					case IResourceDelta.ADDED:
						processChildren = isJavaProject;
						affectedProjects.add(project.getFullPath());
						break;
					case IResourceDelta.CHANGED:
						processChildren = isJavaProject;
						if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
							// project opened or closed: remember  project and its dependents
							affectedProjects.add(project.getFullPath());
							if (isJavaProject) {
								JavaProject javaProject = (JavaProject)JavaCore.create(project);
								javaProject.updateClasspathMarkers(preferredClasspaths, preferredOutputs); // in case .classpath got modified while closed
							}
						} else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
							boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(project) != null;
							if (wasJavaProject && !isJavaProject) {
								// project no longer has Java nature, discard Java related obsolete markers
								affectedProjects.add(project.getFullPath());
								// flush classpath markers
								JavaProject javaProject = (JavaProject)JavaCore.create(project);
								javaProject.
									flushClasspathProblemMarkers(
										true, // flush cycle markers
										true  //flush classpath format markers
									);
									
								// remove problems and tasks created  by the builder
								JavaBuilder.removeProblemsAndTasksFor(project);
							}
						} else if (isJavaProject) {
							// check if all entries exist
							try {
								JavaProject javaProject = (JavaProject)JavaCore.create(project);
								javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, 	true/*generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
							} catch (JavaModelException e) {
								// project doesn't exist: ignore
							}
						}
						break;
					case IResourceDelta.REMOVED:
						affectedProjects.add(project.getFullPath());
						break;
				}
				break;
			case IResource.FILE :
				/* check classpath file change */
				IFile file = (IFile) resource;
				if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
					affectedProjects.add(file.getProject().getFullPath());
					JavaProject javaProject = (JavaProject)JavaCore.create(file.getProject());
					javaProject.updateClasspathMarkers(preferredClasspaths, preferredOutputs);
					break;
				}
//				/* check custom preference file change */
//				if (file.getName().equals(JavaProject.PREF_FILENAME)) {
//					reconcilePreferenceFileUpdate(delta, file, project);
//					break;
//				}
				break;
		}
		if (processChildren) {
			IResourceDelta[] children = delta.getAffectedChildren();
			for (int i = 0; i < children.length; i++) {
				updateClasspathMarkers(children[i], affectedProjects, preferredClasspaths, preferredOutputs);
			}
		}
	}

	/*
	 * Update the .classpath format, missing entries and cycle markers for the projects affected by the given delta.
	 */
	private void updateClasspathMarkers(IResourceDelta delta) {
		
		Map preferredClasspaths = new HashMap(5);
		Map preferredOutputs = new HashMap(5);
		HashSet affectedProjects = new HashSet(5);
		
		// read .classpath files that have changed, and create markers if format is wrong or if an entry cannot be found
		JavaModel.flushExternalFileCache();
		updateClasspathMarkers(delta, affectedProjects, preferredClasspaths, preferredOutputs); 
	
		// update .classpath format markers for affected projects (dependent projects 
		// or projects that reference a library in one of the projects that have changed)
		if (!affectedProjects.isEmpty()) {
			try {
				IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
				IProject[] projects = workspaceRoot.getProjects();
				int length = projects.length;
				for (int i = 0; i < length; i++){
					IProject project = projects[i];
					JavaProject javaProject = (JavaProject)JavaCore.create(project);
					if (preferredClasspaths.get(javaProject) == null) { // not already updated
						try {
							IPath projectPath = project.getFullPath();
							IClasspathEntry[] classpath = javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/); // allowed to reuse model cache
							for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
								IClasspathEntry entry = classpath[j];
								switch (entry.getEntryKind()) {
									case IClasspathEntry.CPE_PROJECT:
										if (affectedProjects.contains(entry.getPath())) {
											javaProject.updateClasspathMarkers(null, null);
										}
										break;
									case IClasspathEntry.CPE_LIBRARY:
										IPath entryPath = entry.getPath();
										IPath libProjectPath = entryPath.removeLastSegments(entryPath.segmentCount()-1);
										if (!libProjectPath.equals(projectPath) // if library contained in another project
												&& affectedProjects.contains(libProjectPath)) {
											javaProject.updateClasspathMarkers(null, null);
										}
										break;
								}
							}
						} catch(JavaModelException e) {
								// project no longer exists
						}
					}
				}

				// update all cycle markers
				JavaProject.updateAllCycleMarkers(preferredClasspaths);
			} catch(JavaModelException e) {
				// project no longer exists
			}
		}
	}
	
	/*
	 * Update the current delta (ie. add/remove/change the given element) and update the correponding index.
	 * Returns whether the children of the given delta must be processed.
	 * @throws a JavaModelException if the delta doesn't correspond to a java element of the given type.
	 */
	public boolean updateCurrentDeltaAndIndex(IResourceDelta delta, int elementType, RootInfo rootInfo) {
		Openable element;
		switch (delta.getKind()) {
			case IResourceDelta.ADDED :
				IResource deltaRes = delta.getResource();
				element = createElement(deltaRes, elementType, rootInfo);
				if (element == null) {
					// resource might be containing shared roots (see bug 19058)
					this.state.updateRoots(deltaRes.getFullPath(), delta, this);
					return rootInfo != null && rootInfo.inclusionPatterns != null;
				}
				updateIndex(element, delta);
				elementAdded(element, delta, rootInfo);
				return elementType == IJavaElement.PACKAGE_FRAGMENT;
			case IResourceDelta.REMOVED :
				deltaRes = delta.getResource();
				element = createElement(deltaRes, elementType, rootInfo);
				if (element == null) {
					// resource might be containing shared roots (see bug 19058)
					this.state.updateRoots(deltaRes.getFullPath(), delta, this);
					return rootInfo != null && rootInfo.inclusionPatterns != null;
				}
				updateIndex(element, delta);
				elementRemoved(element, delta, rootInfo);
	
				if (deltaRes.getType() == IResource.PROJECT){			
					// reset the corresponding project built state, since cannot reuse if added back
					this.manager.setLastBuiltState((IProject)deltaRes, null /*no state*/);
				}
				return elementType == IJavaElement.PACKAGE_FRAGMENT;
			case IResourceDelta.CHANGED :
				int flags = delta.getFlags();
				if ((flags & IResourceDelta.CONTENT) != 0 || (flags & IResourceDelta.ENCODING) != 0) {
					// content or encoding has changed
					element = createElement(delta.getResource(), elementType, rootInfo);
					if (element == null) return false;
					updateIndex(element, delta);
					contentChanged(element);
				} else if (elementType == IJavaElement.JAVA_PROJECT) {
					if ((flags & IResourceDelta.OPEN) != 0) {
						// project has been opened or closed
						IProject res = (IProject)delta.getResource();
						element = createElement(res, elementType, rootInfo);
						if (element == null) {
							// resource might be containing shared roots (see bug 19058)
							this.state.updateRoots(res.getFullPath(), delta, this);
							return false;
						}
						if (res.isOpen()) {
							if (JavaProject.hasJavaNature(res)) {
								addToParentInfo(element);
								currentDelta().opened(element);
								this.state.updateRoots(element.getPath(), delta, this);
								
								// refresh pkg fragment roots and caches of the project (and its dependents)
								this.rootsToRefresh.add(element);
								this.projectCachesToReset.add(element);
								
								this.manager.indexManager.indexAll(res);
							}
						} else {
							JavaModel javaModel = this.manager.getJavaModel();
							boolean wasJavaProject = javaModel.findJavaProject(res) != null;
							if (wasJavaProject) {
								close(element);
								removeFromParentInfo(element);
								currentDelta().closed(element);
								this.manager.indexManager.discardJobs(element.getElementName());
								this.manager.indexManager.removeIndexFamily(res.getFullPath());
							}
						}
						return false; // when a project is open/closed don't process children
					}
					if ((flags & IResourceDelta.DESCRIPTION) != 0) {
						IProject res = (IProject)delta.getResource();
						JavaModel javaModel = this.manager.getJavaModel();
						boolean wasJavaProject = javaModel.findJavaProject(res) != null;
						boolean isJavaProject = JavaProject.hasJavaNature(res);
						if (wasJavaProject != isJavaProject) {
							// project's nature has been added or removed
							element = this.createElement(res, elementType, rootInfo);
							if (element == null) return false; // note its resources are still visible as roots to other projects
							if (isJavaProject) {
								elementAdded(element, delta, rootInfo);
								this.manager.indexManager.indexAll(res);
							} else {
								elementRemoved(element, delta, rootInfo);
								this.manager.indexManager.discardJobs(element.getElementName());
								this.manager.indexManager.removeIndexFamily(res.getFullPath());
								// reset the corresponding project built state, since cannot reuse if added back
								this.manager.setLastBuiltState(res, null /*no state*/);
							}
							return false; // when a project's nature is added/removed don't process children
						}
					}
				}
				return true;
		}
		return true;
	}
	private void updateIndex(Openable element, IResourceDelta delta) {
	
		IndexManager indexManager = this.manager.indexManager;
		if (indexManager == null)
			return;
	
		switch (element.getElementType()) {
			case IJavaElement.JAVA_PROJECT :
				switch (delta.getKind()) {
					case IResourceDelta.ADDED :
						indexManager.indexAll(element.getJavaProject().getProject());
						break;
					case IResourceDelta.REMOVED :
						indexManager.removeIndexFamily(element.getJavaProject().getProject().getFullPath());
						// NB: Discarding index jobs belonging to this project was done during PRE_DELETE
						break;
					// NB: Update of index if project is opened, closed, or its java nature is added or removed
					//     is done in updateCurrentDeltaAndIndex
				}
				break;
			case IJavaElement.PACKAGE_FRAGMENT_ROOT :
				if (element instanceof JarPackageFragmentRoot) {
					JarPackageFragmentRoot root = (JarPackageFragmentRoot)element;
					// index jar file only once (if the root is in its declaring project)
					IPath jarPath = root.getPath();
					switch (delta.getKind()) {
						case IResourceDelta.ADDED:
							// index the new jar
							indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
							break;
						case IResourceDelta.CHANGED:
							// first remove the index so that it is forced to be re-indexed
							indexManager.removeIndex(jarPath);
							// then index the jar
							indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
							break;
						case IResourceDelta.REMOVED:
							// the jar was physically removed: remove the index
							indexManager.discardJobs(jarPath.toString());
							indexManager.removeIndex(jarPath);
							break;
					}
					break;
				}
				int kind = delta.getKind();
				if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
					PackageFragmentRoot root = (PackageFragmentRoot)element;
					this.updateRootIndex(root, CharOperation.NO_STRINGS, delta);
					break;
				}
				// don't break as packages of the package fragment root can be indexed below
			case IJavaElement.PACKAGE_FRAGMENT :
				switch (delta.getKind()) {
					case IResourceDelta.ADDED:
					case IResourceDelta.REMOVED:
						IPackageFragment pkg = null;
						if (element instanceof IPackageFragmentRoot) {
							PackageFragmentRoot root = (PackageFragmentRoot)element;
							pkg = root.getPackageFragment(CharOperation.NO_STRINGS);
						} else {
							pkg = (IPackageFragment)element;
						}
						RootInfo rootInfo = rootInfo(pkg.getParent().getPath(), delta.getKind());
						boolean isSource = 
							rootInfo == null // if null, defaults to source
							|| rootInfo.entryKind == IClasspathEntry.CPE_SOURCE;
						IResourceDelta[] children = delta.getAffectedChildren();
						for (int i = 0, length = children.length; i < length; i++) {
							IResourceDelta child = children[i];
							IResource resource = child.getResource();
							// TODO (philippe) Why do this? Every child is added anyway as the delta is walked
							if (resource instanceof IFile) {
								String name = resource.getName();
								if (isSource) {
									if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name)) {
										Openable cu = (Openable)pkg.getCompilationUnit(name);
										this.updateIndex(cu, child);
									}
								} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
									Openable classFile = (Openable)pkg.getClassFile(name);
									this.updateIndex(classFile, child);
								}
							}
						}
						break;
				}
				break;
			case IJavaElement.CLASS_FILE :
				IFile file = (IFile) delta.getResource();
				IJavaProject project = element.getJavaProject();
				IPath binaryFolderPath = element.getPackageFragmentRoot().getPath();
				// if the class file is part of the binary output, it has been created by
				// the java builder -> ignore
				try {
					if (binaryFolderPath.equals(project.getOutputLocation())) {
						break;
					}
				} catch (JavaModelException e) {
					// project doesn't exist: ignore
				}
				switch (delta.getKind()) {
					case IResourceDelta.CHANGED :
						// no need to index if the content has not changed
						int flags = delta.getFlags();
						if ((flags & IResourceDelta.CONTENT) == 0 && (flags & IResourceDelta.ENCODING) == 0)
							break;
					case IResourceDelta.ADDED :
						indexManager.addBinary(file, binaryFolderPath);
						break;
					case IResourceDelta.REMOVED :
						indexManager.remove(file.getFullPath().toString(), binaryFolderPath);
						break;
				}
				break;
			case IJavaElement.COMPILATION_UNIT :
				file = (IFile) delta.getResource();
				switch (delta.getKind()) {
					case IResourceDelta.CHANGED :
						// no need to index if the content has not changed
						int flags = delta.getFlags();
						if ((flags & IResourceDelta.CONTENT) == 0 && (flags & IResourceDelta.ENCODING) == 0)
							break;
					case IResourceDelta.ADDED :
						indexManager.addSource(file, file.getProject().getFullPath());
						break;
					case IResourceDelta.REMOVED :
						indexManager.remove(file.getFullPath().toString(), file.getProject().getFullPath());
						break;
				}
		}
	}
	/*
	 * Update Java Model given some delta
	 */
	public void updateJavaModel(IJavaElementDelta customDelta) {

		if (customDelta == null){
			for (int i = 0, length = this.javaModelDeltas.size(); i < length; i++){
				IJavaElementDelta delta = (IJavaElementDelta)this.javaModelDeltas.get(i);
				this.modelUpdater.processJavaDelta(delta);
			}
		} else {
			this.modelUpdater.processJavaDelta(customDelta);
		}
	}
	/*
	 * Updates the index of the given root (assuming it's an addition or a removal).
	 * This is done recusively, pkg being the current package.
	 */
	private void updateRootIndex(PackageFragmentRoot root, String[] pkgName, IResourceDelta delta) {
		Openable pkg = root.getPackageFragment(pkgName);
		this.updateIndex(pkg, delta);
		IResourceDelta[] children = delta.getAffectedChildren();
		for (int i = 0, length = children.length; i < length; i++) {
			IResourceDelta child = children[i];
			IResource resource = child.getResource();
			if (resource instanceof IFolder) {
				String[] subpkgName = Util.arrayConcat(pkgName, resource.getName());
				this.updateRootIndex(root, subpkgName, child);
			}
		}
	}
}
