Parser detects wrong include files now
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / DeltaProcessor.java
index ac3dd0f..a0bf965 100644 (file)
@@ -12,16 +12,25 @@ package net.sourceforge.phpdt.internal.core;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Map;
 
 import net.sourceforge.phpdt.core.ElementChangedEvent;
+import net.sourceforge.phpdt.core.IClasspathEntry;
+import net.sourceforge.phpdt.core.IElementChangedListener;
 import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaElementDelta;
+import net.sourceforge.phpdt.core.IJavaModel;
 import net.sourceforge.phpdt.core.IJavaProject;
 import net.sourceforge.phpdt.core.JavaCore;
 import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.internal.core.builder.PHPBuilder;
+import net.sourceforge.phpdt.internal.core.util.Util;
 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
@@ -31,8 +40,12 @@ import org.eclipse.core.resources.IResourceChangeListener;
 import org.eclipse.core.resources.IResourceDelta;
 import org.eclipse.core.resources.IResourceDeltaVisitor;
 import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
 
 
 /**
@@ -53,8 +66,11 @@ public class DeltaProcessor implements IResourceChangeListener {
        final static String EXTERNAL_JAR_UNCHANGED = "external jar unchanged"; //$NON-NLS-1$
        final static String INTERNAL_JAR_IGNORE = "internal jar ignore"; //$NON-NLS-1$
        
-       final static int NON_JAVA_RESOURCE = -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
        /**
         * The <code>JavaElementDelta</code> corresponding to the <code>IResourceDelta</code> being translated.
         */
@@ -88,14 +104,38 @@ public class DeltaProcessor implements IResourceChangeListener {
         * This is used as a stack of java elements (using getParent() to pop it, and 
         * using the various get*(...) to push it. */
        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;
+       
+       
        public HashMap externalTimeStamps = new HashMap();
        public HashSet projectsToUpdate = new HashSet();
        // list of root projects which namelookup caches need to be updated for dependents
        // TODO: (jerome) is it needed? projectsToUpdate might be sufficient
        public HashSet projectsForDependentNamelookupRefresh = new HashSet();  
        
-       JavaModelManager manager;
+       /*
+        * The global state of delta processing.
+        */
+       private DeltaProcessingState state;
+       
+       /*
+        * The Java model manager
+        */
+       private JavaModelManager manager;
        
        /* A table from IJavaProject to an array of IPackageFragmentRoot.
         * This table contains the pkg fragment roots of the project that are being deleted.
@@ -107,7 +147,6 @@ public class DeltaProcessor implements IResourceChangeListener {
         * This is null if no refresh is needed.
         */
        HashSet refreshedElements;
-       public static boolean VERBOSE = false;
        
        class OutputsInfo {
                IPath[] paths;
@@ -185,10 +224,19 @@ public class DeltaProcessor implements IResourceChangeListener {
                }
        }
 
-       DeltaProcessor(JavaModelManager manager) {
+//     DeltaProcessor(JavaModelManager manager) {
+//             this.manager = manager;
+//     }
+
+       /*
+        * 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.
@@ -667,7 +715,7 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                                     } else if (((JavaProject)root.getJavaProject()).contains(resource)) {
 //                                             // create package handle
 //                                             IPath pkgPath = path.removeFirstSegments(root.getPath().segmentCount());
-//                                             String pkg = Util.packageName(pkgPath);
+//                                             String pkg = ProjectPrefUtil.packageName(pkgPath);
 //                                             if (pkg == null) return null;
 //                                             element = root.getPackageFragment(pkg);
 //                                     }
@@ -688,7 +736,7 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                                                     IPackageFragmentRoot root = (IPackageFragmentRoot)this.currentElement;
 //                                                     IPath rootPath = root.getPath();
 //                                                     IPath pkgPath = path.removeLastSegments(1);
-//                                                     String pkgName = Util.packageName(pkgPath.removeFirstSegments(rootPath.segmentCount()));
+//                                                     String pkgName = ProjectPrefUtil.packageName(pkgPath.removeFirstSegments(rootPath.segmentCount()));
 //                                                     if (pkgName != null) {
 //                                                             pkgFragment = root.getPackageFragment(pkgName);
 //                                                     }
@@ -876,7 +924,7 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                                                     IResource resource = child.getResource();
 //                                                     if (resource instanceof IFolder) {
 //                                                             String folderName = resource.getName();
-//                                                             if (Util.isValidFolderNameForPackage(folderName)) {
+//                                                             if (ProjectPrefUtil.isValidFolderNameForPackage(folderName)) {
 //                                                                     String subpkgName = 
 //                                                                             name.length() == 0 ? 
 //                                                                                     folderName : 
@@ -986,7 +1034,7 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                                             IResource resource = child.getResource();
 //                                             if (resource instanceof IFolder) {
 //                                                     String folderName = resource.getName();
-//                                                     if (Util.isValidFolderNameForPackage(folderName)) {
+//                                                     if (ProjectPrefUtil.isValidFolderNameForPackage(folderName)) {
 //                                                             String subpkgName = 
 //                                                                     name.length() == 0 ? 
 //                                                                             folderName : 
@@ -1026,20 +1074,20 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                             if (rootInfo == null) {
 //                                     rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
 //                             }
-//                             if (rootInfo == null || Util.isExcluded(res, rootInfo.exclusionPatterns)) {
+//                             if (rootInfo == null || ProjectPrefUtil.isExcluded(res, rootInfo.exclusionPatterns)) {
 //                                     return NON_JAVA_RESOURCE;
 //                             }
 //                             if (res instanceof IFolder) {
-//                                     if (Util.isValidFolderNameForPackage(res.getName())) {
+//                                     if (ProjectPrefUtil.isValidFolderNameForPackage(res.getName())) {
 //                                             return IJavaElement.PACKAGE_FRAGMENT;
 //                                     } else {
 //                                             return NON_JAVA_RESOURCE;
 //                                     }
 //                             } else {
 //                                     String fileName = res.getName();
-//                                     if (Util.isValidCompilationUnitName(fileName)) {
+//                                     if (ProjectPrefUtil.isValidCompilationUnitName(fileName)) {
 //                                             return IJavaElement.COMPILATION_UNIT;
-//                                     } else if (Util.isValidClassFileName(fileName)) {
+//                                     } else if (ProjectPrefUtil.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
@@ -1061,75 +1109,75 @@ public class DeltaProcessor implements IResourceChangeListener {
                return file.lastModified() + file.length();
        }
 
-//     public void initializeRoots() {
-//             // remember roots infos as old roots infos
-//             this.oldRoots = this.roots == null ? new HashMap() : this.roots;
-//             this.oldOtherRoots = this.otherRoots == null ? new HashMap() : this.otherRoots;
-//             
-//             // recompute root infos only if necessary
-//             if (!rootsAreStale) return;
-//
-//             this.roots = new HashMap();
-//             this.otherRoots = new HashMap();
-//             this.sourceAttachments = new HashMap();
-//             
-//             IJavaModel model = this.manager.getJavaModel();
-//             IJavaProject[] projects;
-//             try {
-//                     projects = model.getJavaProjects();
-//             } catch (JavaModelException e) {
-//                     // nothing can be done
-//                     return;
-//             }
-//             for (int i = 0, length = projects.length; i < length; i++) {
-//                     IJavaProject project = projects[i];
-//                     IClasspathEntry[] classpath;
-//                     try {
-//                             classpath = project.getResolvedClasspath(true);
-//                     } catch (JavaModelException e) {
-//                             // continue with next project
-//                             continue;
-//                     }
-//                     for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) {
-//                             IClasspathEntry entry = classpath[j];
-//                             if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
-//                             
-                               // root path
-//                             IPath path = entry.getPath();
-//                             if (this.roots.get(path) == null) {
-//                                     this.roots.put(path, new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
-//                             } else {
-//                                     ArrayList rootList = (ArrayList)this.otherRoots.get(path);
-//                                     if (rootList == null) {
-//                                             rootList = new ArrayList();
-//                                             this.otherRoots.put(path, rootList);
-//                                     }
-//                                     rootList.add(new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
-//                             }
-//                             
-//                             // source attachment path
-//                             if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) continue;
-//                             QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$;
-//                             String propertyString = null;
-//                             try {
-//                                     propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
-//                             } catch (CoreException e) {
-//                                     continue;
-//                             }
-//                             IPath sourceAttachmentPath;
+       public void initializeRoots() {
+               // remember roots infos as old roots infos
+               this.oldRoots = this.roots == null ? new HashMap() : this.roots;
+               this.oldOtherRoots = this.otherRoots == null ? new HashMap() : this.otherRoots;
+               
+               // recompute root infos only if necessary
+               if (!rootsAreStale) return;
+
+               this.roots = new HashMap();
+               this.otherRoots = new HashMap();
+               this.sourceAttachments = new HashMap();
+               
+               IJavaModel model = this.manager.getJavaModel();
+               IJavaProject[] projects;
+               try {
+                       projects = model.getJavaProjects();
+               } catch (JavaModelException e) {
+                       // nothing can be done
+                       return;
+               }
+               for (int i = 0, length = projects.length; i < length; i++) {
+                       IJavaProject project = projects[i];
+                       IClasspathEntry[] classpath;
+                       try {
+                               classpath = project.getResolvedClasspath(true);
+                       } catch (JavaModelException e) {
+                               // continue with next project
+                               continue;
+                       }
+                       for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) {
+                               IClasspathEntry entry = classpath[j];
+                               if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
+                               
+//                              root path
+                               IPath path = entry.getPath();
+                               if (this.roots.get(path) == null) {
+                                       this.roots.put(path, new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
+                               } else {
+                                       ArrayList rootList = (ArrayList)this.otherRoots.get(path);
+                                       if (rootList == null) {
+                                               rootList = new ArrayList();
+                                               this.otherRoots.put(path, rootList);
+                                       }
+                                       rootList.add(new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
+                               }
+                               
+                               // source attachment path
+                               if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) continue;
+                               QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$;
+                               String propertyString = null;
+                               try {
+                                       propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
+                               } catch (CoreException e) {
+                                       continue;
+                               }
+                               IPath sourceAttachmentPath;
 //                             if (propertyString != null) {
 //                                     int index= propertyString.lastIndexOf(JarPackageFragmentRoot.ATTACHMENT_PROPERTY_DELIMITER);
 //                                     sourceAttachmentPath = (index < 0) ?  new Path(propertyString) : new Path(propertyString.substring(0, index));
 //                             } else {
-//                                     sourceAttachmentPath = entry.getSourceAttachmentPath();
-//                             }
-//                             if (sourceAttachmentPath != null) {
-//                                     this.sourceAttachments.put(sourceAttachmentPath, path);
+                                       sourceAttachmentPath = entry.getSourceAttachmentPath();
 //                             }
-//                     }
-//             }
-//             this.rootsAreStale = false;
-//     }
+                               if (sourceAttachmentPath != null) {
+                                       this.sourceAttachments.put(sourceAttachmentPath, path);
+                               }
+                       }
+               }
+               this.rootsAreStale = false;
+       }
 
        /*
         * Returns whether a given delta contains some information relevant to the JavaModel,
@@ -1198,96 +1246,48 @@ public class DeltaProcessor implements IResourceChangeListener {
                }
                return false;
        }
-
-       /**
-        * 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>
+       /*
+        * Merges all awaiting deltas.
         */
-//     protected 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 elementDelta = currentDelta().find(element);
-//             if (elementDelta == null) {
-//                     currentDelta().changed(element, IJavaElementDelta.F_CONTENT);
-//                     elementDelta = currentDelta().find(element);
-//             }
-//             elementDelta.addResourceDelta(delta);
-//     }
-//     private OutputsInfo outputsInfo(RootInfo rootInfo, IResource res) {
-//             try {
-//                     IJavaProject proj =
-//                             rootInfo == null ?
-//                                     (IJavaProject)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);
-//                             } else {
-//                                     IClasspathEntry[] classpath = proj.getResolvedClasspath(true);
-//                                     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) {
-//             }
-//             return null;
-//     }
+       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;
+       }       
        
        /**
         * Check whether the updated file is affecting some of the properties of a given project (like
@@ -1398,75 +1398,6 @@ public class DeltaProcessor implements IResourceChangeListener {
         * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
         * relevant <code>JavaModel</code>s.
         */
-//     public 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.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
-//                             if (!this.traverseDelta(delta, elementType, rootInfo, null) 
-//                                             || (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) {
-//                                     }
-//                             }
-//
-//                     }
-//                     
-//                     // update package fragment roots of projects that were affected
-//                     Iterator iterator = this.projectsToUpdate.iterator();
-//                     while (iterator.hasNext()) {
-//                             JavaProject project = (JavaProject)iterator.next();
-//                             project.updatePackageFragmentRoots();
-//                     }
-//     
-//                     updateDependentNamelookups();
-//
-//                     return this.currentDelta;
-//             } finally {
-//                     this.currentDelta = null;
-//                     this.projectsToUpdate.clear();
-//                     this.projectsForDependentNamelookupRefresh.clear();
-//             }
-//     }
 
        /**
         * Update the JavaModel according to a .classpath file change. The file can have changed as a result of a previous
@@ -1483,7 +1414,7 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                                     }
 //                             } catch (JavaModelException e) {
 //                                     if (project.getProject().isAccessible()) {
-//                                             Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
+//                                             ProjectPrefUtil.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
 //                                     }
 //                             }
 //                             break;
@@ -1539,7 +1470,7 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                             } catch (RuntimeException e) {
 //                                     // setRawClasspath might fire a delta, and a listener may throw an exception
 //                                     if (project.getProject().isAccessible()) {
-//                                             Util.log(e, "Could not set classpath for "+ project.getPath()); //$NON-NLS-1$
+//                                             ProjectPrefUtil.log(e, "Could not set classpath for "+ project.getPath()); //$NON-NLS-1$
 //                                     }
 //                                     break;
 //                             } catch (JavaModelException e) { // CP failed validation
@@ -1548,11 +1479,11 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                                                     // happens if the .classpath could not be written to disk
 //                                                     project.createClasspathProblemMarker(new JavaModelStatus(
 //                                                                     IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
-//                                                                     Util.bind("classpath.couldNotWriteClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
+//                                                                     ProjectPrefUtil.bind("classpath.couldNotWriteClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
 //                                             } else {
 //                                                     project.createClasspathProblemMarker(new JavaModelStatus(
 //                                                                     IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
-//                                                                     Util.bind("classpath.invalidClasspathInClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
+//                                                                     ProjectPrefUtil.bind("classpath.invalidClasspathInClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
 //                                             }                       
 //                                     }
 //                                     break;
@@ -1627,7 +1558,12 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                             //fCurrentDelta.changed(project, IJavaElementDelta.F_OPTIONS_CHANGED);                          
 //             }
 //     }
-
+       /*
+        * 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,
@@ -1645,6 +1581,7 @@ public class DeltaProcessor implements IResourceChangeListener {
                        }
                }
        }
+       
        /**
         * Notification that some resource changes have happened
         * on the platform, and that the Java Model should update any required
@@ -1655,73 +1592,524 @@ public class DeltaProcessor implements IResourceChangeListener {
         * @see IResource 
         */
        public void resourceChanged(IResourceChangeEvent event) {
-       
-               if (event.getSource() instanceof IWorkspace) {
-                       IResource resource = event.getResource();
-                       IResourceDelta delta = event.getDelta();
-                       
-                       switch(event.getType()){
-                               case IResourceChangeEvent.PRE_DELETE :
+         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(PHPeclipsePlugin.PHP_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 {
-                                               if(resource.getType() == IResource.PROJECT 
-                                                       && ((IProject) resource).hasNature(JavaCore.NATURE_ID)) {
-                                               // TODO khartlage temp-del
-//                                                     this.deleting((IProject)resource);
+                                               try {
+                                                       stopDeltas();
+//                                                     checkProjectsBeingAddedOrRemoved(delta);
+//                                                     if (this.refreshedElements != null) {
+//                                                             createExternalArchiveDelta(null);
+//                                                     }
+                                                       IJavaElementDelta translatedDelta = processResourceDelta(delta);
+                                                       if (translatedDelta != null) { 
+                                                               registerJavaModelDelta(translatedDelta);
+                                                       }
+                                               } finally {
+                                                       startDeltas();
                                                }
-                                       } catch(CoreException e){
+//                                             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_AUTO_BUILD :
-//                     TODO khartlage temp-del
-//                                     if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
-//                                             this.checkProjectsBeingAddedOrRemoved(delta);
-//                                             
-//                                             // update the classpath related markers
-//                                             this.updateClasspathMarkers();
-//     
-//                                             // the following will close project if affected by the property file change
-//                                             try {
-//                                                     // don't fire classpath change deltas right away, but batch them
-//                                                     this.manager.stopDeltas();
-//                                                     this.performPreBuildCheck(delta, null); 
-//                                             } finally {
-//                                                     this.manager.startDeltas();
+                               }
+                               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);
+                                       PHPBuilder.buildStarting();
+                               }
+                               // does not fire any deltas
+                               return;
+
+                       case IResourceChangeEvent.POST_BUILD :
+                               PHPBuilder.buildFinished();
+                               return;
+               }
+       }
+//             // jsurfer TODO compare 3.0 sources
+//             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(PHPeclipsePlugin.PHP_NATURE_ID)) {
+//                                             // TODO jsurfer temp-del
+////                                                   this.deleting((IProject)resource);
 //                                             }
+//                                     } catch(CoreException e){
 //                                     }
-                                       // only fire already computed deltas (resource ones will be processed in post change only)
-                                       this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
-                                       break;
+//                                     return;
+//                                     
+//                             case IResourceChangeEvent.PRE_BUILD :
+////                   TODO jsurfer temp-del
+////                                   if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
+////                                           this.checkProjectsBeingAddedOrRemoved(delta);
+////                                           
+////                                           // update the classpath related markers
+////                                           this.updateClasspathMarkers();
+////   
+////                                           // the following will close project if affected by the property file change
+////                                           try {
+////                                                   // don't fire classpath change deltas right away, but batch them
+////                                                   this.manager.stopDeltas();
+////                                                   this.performPreBuildCheck(delta, null); 
+////                                           } finally {
+////                                                   this.manager.startDeltas();
+////                                           }
+////                                   }
+//                                     // only fire already computed deltas (resource ones will be processed in post change only)
+//                                     this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
+//                                     break;
+//
+//                             case IResourceChangeEvent.POST_BUILD :
+////                   TODO jsurfer temp-del
+////                                   JavaBuilder.finishedBuilding(event);
+//                                     break;
+//                                     
+//                             case IResourceChangeEvent.POST_CHANGE :
+////                   TODO jsurfer temp-del
+////                                   if (isAffectedBy(delta)) {
+////                                           try {
+////                                                   if (this.refreshedElements != null) {
+////                                                           try {
+////                                                                   createExternalArchiveDelta(null);
+////                                                           } catch (JavaModelException e) {
+////                                                                   e.printStackTrace();
+////                                                           }
+////                                                   }
+////                                                   IJavaElementDelta translatedDelta = this.processResourceDelta(delta);
+////                                                   if (translatedDelta != null) { 
+////                                                           this.manager.registerJavaModelDelta(translatedDelta);
+////                                                   }
+////                                                   this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
+////                                           } finally {
+////                                                   // workaround for bug 15168 circular errors not reported 
+////                                                   this.manager.javaProjectsCache = null;
+////                                                   this.removedRoots = null;
+////                                           }
+////                                   }
+//                     }
+//             }
+       }
+       /*
+        * 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;
+       }
+       /*
+        * 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());
 
-                               case IResourceChangeEvent.POST_AUTO_BUILD :
-//                     TODO khartlage temp-del
-//                                     JavaBuilder.finishedBuilding(event);
-                                       break;
-                                       
-                               case IResourceChangeEvent.POST_CHANGE :
-//                     TODO khartlage temp-del
-//                                     if (isAffectedBy(delta)) {
-//                                             try {
-//                                                     if (this.refreshedElements != null) {
-//                                                             try {
-//                                                                     createExternalArchiveDelta(null);
-//                                                             } catch (JavaModelException e) {
-//                                                                     e.printStackTrace();
+                       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));
+                       }
+                       
+                       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);
+
+               } catch (JavaModelException e) {
+                       // java project doesn't exist: ignore
+               }
+       }
+       /*
+        * 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();
+               }
+       }
+       
+       /*
+        * 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;
 //                                                             }
 //                                                     }
-//                                                     IJavaElementDelta translatedDelta = this.processResourceDelta(delta);
-//                                                     if (translatedDelta != null) { 
-//                                                             this.manager.registerJavaModelDelta(translatedDelta);
+//                                                     // add child as non java resource
+//                                                     try {
+//                                                             nonJavaResourcesChanged(parent, child);
+//                                                     } catch (JavaModelException e) {
+//                                                             // ignore
 //                                                     }
-//                                                     this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
-//                                             } finally {
-//                                                     // workaround for bug 15168 circular errors not reported 
-//                                                     this.manager.javaProjectsCache = null;
-//                                                     this.removedRoots = null;
+//                                             } 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
+//     }
+       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) {
+//                                     ProjectPrefUtil.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);
+       }
+       /*
+        * Flushes all deltas without firing them.
+        */
+       public void flush() {
+               this.javaModelDeltas = new ArrayList();
        }
        /*
         * Finds the root info this path is included in.
@@ -1736,6 +2124,89 @@ public class DeltaProcessor implements IResourceChangeListener {
                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 the root info for the given path. Look in the old roots table if kind is REMOVED.
         */
        RootInfo rootInfo(IPath path, int kind) {
@@ -2142,10 +2613,10 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                                             IResource resource = child.getResource();
 //                                             if (resource instanceof IFile) {
 //                                                     String name = resource.getName();
-//                                                     if (Util.isJavaFileName(name)) {
+//                                                     if (ProjectPrefUtil.isJavaFileName(name)) {
 //                                                             Openable cu = (Openable)pkg.getCompilationUnit(name);
 //                                                             this.updateIndex(cu, child);
-//                                                     } else if (Util.isClassFileName(name)) {
+//                                                     } else if (ProjectPrefUtil.isClassFileName(name)) {
 //                                                             Openable classFile = (Openable)pkg.getClassFile(name);
 //                                                             this.updateIndex(classFile, child);
 //                                                     }