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

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.sse.core.internal.Logger;

/**
 * <p>
 * A generic class for implementing a resource index manager. It is important
 * to note that this only provides the framework for managing an index, not
 * actually indexing. The subtle difference is that the manager is in charge
 * of paying attention to all of the resource actions that take place in the
 * workspace and filtering those actions down to simple actions that need to
 * be performed on whatever index this manager is managing.
 * </p>
 * 
 * <p>
 * The manager does its very best to make sure the index is always consistent,
 * even if resource events take place when the manager is not running. In the
 * event that the manager determines it has missed, lost, or corrupted any
 * resource change events that have occurred before, during, or after its
 * activation or deactivation then the manager will inspect the entire
 * workspace to insure the index it is managing is consistent.
 * </p>
 * 
 * <p>
 * This class and its contents are <b>PROVISIONAL</b>. They can and very likely will
 * change prior to finalization in the next main release.
 * </p>
 * 
 */
public abstract class AbstractIndexManager {
	
	/** Used to encode path bytes in case they contain double byte characters */
	private static final String ENCODING_UTF16 = "utf16"; //$NON-NLS-1$
	
	/** Default time to wait for other tasks to finish */
	private static final int WAIT_TIME = 300;
	
	/**
	 * <p>Used to report progress on jobs where the total work to complete is unknown.
	 * The created effect is a progress bar that moves but that will never complete.</p>
	 */
	private static final int UNKNOWN_WORK = 100;
	
	/** The amount of events to batch up before sending them off to the processing job*/
	private static final int BATCH_UP_AMOUNT = 100;
	
	/** If this file exists then a full workspace re-processing is needed */ 
	private static final String RE_PROCESS_FILE_NAME = ".re-process"; //$NON-NLS-1$
	
	/** Common error message to log */
	private static final String LOG_ERROR_INDEX_INVALID =
		"Index may become invalid, incomplete, or enter some other inconsistent state."; //$NON-NLS-1$
	
	/** State: manager is stopped */
	private static final byte STATE_DISABLED = 0;
	
	/** State: manager is running */
	private static final byte STATE_ENABLED = 1;
	
	/** Action: add to index */
	protected static final byte ACTION_ADD = 0;
	
	/** Action: remove from index */
	protected static final byte ACTION_REMOVE = 1;
	
	/** Action: add to index caused by move operation */
	protected static final byte ACTION_ADD_MOVE_FROM = 2;
	
	/** Action: remove from index caused by move operation */
	protected static final byte ACTION_REMOVE_MOVE_TO = 3;
	
	/** Source: action originated from resource change event */
	protected static final byte SOURCE_RESOURCE_CHANGE = 0;
	
	/** Source: action originated from workspace scan */
	protected static final byte SOURCE_WORKSPACE_SCAN = 1;
	
	/** Source: action originated from saved state */
	protected static final byte SOURCE_SAVED_STATE = 2;
	
	/** Source: preserved resources to index */
	protected static final byte SOURCE_PRESERVED_RESOURCES_TO_INDEX = 3;
	
	/** the name of this index manager */
	private String fName;
	
	/** Message to use when manager is running */
	private String fMessage_Running;
	
	/** Message to use when manager is initializing */
	private String fMessage_Initializing;
	
	/**
	 * <p>Message to use when manager is processing files.
	 * Should contain one parameter to be filled in with the number of files to process.</p>
	 */
	private String fMessage_ProcessingFiles;
	
	/** {@link IResourceChangeListener} to listen for file changes */
	private ResourceChangeListener fResourceChangeListener;
	
	/** The {@link Job} that does all of the indexing */
	private ResourceEventProcessingJob fResourceEventProcessingJob;
	
	/** A {@link Job} to search the workspace for all files */
	private Job fWorkspaceVisitorJob;
	
	/**
	 * <p>Current state of the manager</p>
	 * 
	 * @see #STATE_DISABLED
	 * @see #STATE_ENABLED
	 */
	private volatile byte fState;
	
	/** used to prevent manager from starting and stopping at the same time */
	private Object fStartStopLock = new Object();
	
	/** <code>true</code> if the manager is currently starting, <code>false</code> otherwise */
	private boolean fStarting;

	/**
	 * <p>Creates the manager with a given name.</p>
	 * 
	 * @param name This will be pre-pended to progress reporting messages and thus should
	 * be translated
	 * 
	 * @param messageRunning Message to use when manager is running. Should be user readable.
	 * @param messagegInitializing Message to use when manager is initializing. Should be user readable.
	 * @param messageProcessingFiles Message to use when manager is processing files.
	 * Should contain two parameters to be filled in with the number of files to process, and
	 * the file currently being processed.
	 * Should be user readable.
	 */
	
	protected AbstractIndexManager(String name, String messageRunning,
			String messagegInitializing, String messageProcessingFiles) {
		
		this.fMessage_Running = messageRunning;
		this.fMessage_ProcessingFiles = messageProcessingFiles;
		this.fMessage_Initializing = messagegInitializing;
		
		this.fName = name;
		this.fState = STATE_DISABLED;
		this.fResourceChangeListener = new ResourceChangeListener();
		this.fResourceEventProcessingJob = new ResourceEventProcessingJob();
		this.fStarting = false;
	}
	
	/**
	 * <p>Starts up the {@link AbstractIndexManager}.  If a {@link IResourceDelta}
	 * is provided then it is assumed that all other files in the workspace
	 * have already been index and thus only those in the provided
	 * {@link IResourceDelta} will be processed.  Else if the provided
	 * {@link IResourceDelta} is <code>null</code> it is assumed no files
	 * have been indexed yet so the entire workspace will be searched for
	 * files to be indexed.</p>
	 * 
	 * <p>If {@link IResourceDelta} is provided this will block until that delta
	 * has finished processing.  If no {@link IResourceDelta} provided then a
	 * separate job will be created to process the entire workspace and this method
	 * will return without waiting for that job to complete</p>
	 * 
	 * <p>Will block until {@link #stop()} has finished running if it is
	 * currently running</p>
	 * 
	 * @param savedStateDelta the delta from a saved state, if <code>null</code>
	 * then the entire workspace will be searched for files to index, else
	 * only files in this {@link IResourceDelta} will be indexed
	 * @param monitor This action can not be canceled but this monitor will be used
	 * to report progress
	 */
	public final void start(IResourceDelta savedStateDelta, IProgressMonitor monitor) {
		SubMonitor progress = SubMonitor.convert(monitor);
		synchronized (this.fStartStopLock) {
			this.fStarting = true;
			
			if(this.fState == STATE_DISABLED) {
				//report status
				progress.beginTask(this.fName, 2);
				
				//start listening for resource change events
				this.fResourceChangeListener.start();
				
				//check to see if a full re-index is required
				boolean forcedFullReIndexNeeded = this.isForcedFullReIndexNeeded();
				
				/* start the indexing job only loading preserved state if not doing full index
				 * if failed loading preserved state then force full re-index
				 */
				forcedFullReIndexNeeded = !this.fResourceEventProcessingJob.start(!forcedFullReIndexNeeded,
						progress.newChild(1));
				progress.setWorkRemaining(1);
				
				//don't bother processing saved delta if forced full re-index is needed
				if(!forcedFullReIndexNeeded) {
					/* if there is a delta attempt to process it
					 * else need to do a full workspace index
					 */
					if(savedStateDelta != null) {
						forcedFullReIndexNeeded = false;
						try {
							//deal with reporting progress
							SubMonitor savedStateProgress = progress.newChild(1, SubMonitor.SUPPRESS_NONE);
							
							//process delta
							ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(savedStateProgress,
									AbstractIndexManager.SOURCE_SAVED_STATE);
							savedStateDelta.accept(visitor);
							
							//process any remaining batched up resources to index
							visitor.processBatchedResourceEvents();
						} catch (CoreException e) {
							forcedFullReIndexNeeded = true;
							Logger.logException(this.fName + ": Could not process saved state. " + //$NON-NLS-1$
									"Forced to do a full workspace re-index.", e); //$NON-NLS-1$
						}
					} else {
						forcedFullReIndexNeeded = true;
					}
				}
				progress.worked(1);
				
				//if need to process the entire workspace do so in another job
				if(forcedFullReIndexNeeded){
					this.fWorkspaceVisitorJob = new WorkspaceVisitorJob();
					this.fWorkspaceVisitorJob.schedule();
				}
				
				//update state
				this.fState = STATE_ENABLED;
			}
			this.fStarting = false;
		}
	}
	
	/**
	 * <p>Safely shuts down the manager.</p>
	 * 
	 * <p>This will block until the {@link #start(IResourceDelta, IProgressMonitor)} has
	 * finished (if running).  Also until the current resource event has finished being
	 * processed.  Finally it will block until the events still to be processed by
	 * the processing job have been preserved to be processed on the next call to
	 * {@link #start(IResourceDelta, IProgressMonitor)}.</p>
	 * 
	 * <p>If at any point during this shut down processes something goes wrong the
	 * manager will be sure that on the next call to {@link #start(IResourceDelta, IProgressMonitor)}
	 * the entire workspace will be re-processed.</p>
	 * 
	 * @throws InterruptedException
	 */
	public final void stop() throws InterruptedException {
		synchronized (this.fStartStopLock) {
			if(this.fState != STATE_DISABLED) {
				
				//stop listening for events, and wait for the current event to finish
				this.fResourceChangeListener.stop();
				
				// if currently visiting entire workspace, give up and try again next load
				boolean forceFullReIndexNextStart = false;
				if(this.fWorkspaceVisitorJob != null) {
					if (this.fWorkspaceVisitorJob.getState() != Job.NONE) {
						this.fWorkspaceVisitorJob.cancel();
						
						this.forceFullReIndexNextStart();
						forceFullReIndexNextStart = true;
					}
				}
				
				//stop the indexing job, only preserve if not already forcing a re-index
				forceFullReIndexNextStart = !this.fResourceEventProcessingJob.stop(!forceFullReIndexNextStart);
				
				//if preserving failed, then force re-index
				if(forceFullReIndexNextStart) {
					this.forceFullReIndexNextStart();
				}
				
				//update status
				this.fState = STATE_DISABLED;
			}
		}
	}
	
	/**
	 * @return the name of this indexer
	 */
	protected String getName() {
		return this.fName;
	}
	
	/**
	 * <p>Should be called by a client of the index this manager manages before the index
	 * is accessed, assuming the client wants an index consistent with the latest
	 * resource changes.</p>
	 * 
	 * <p>The supplied monitor will be used to supply user readable progress as the manager
	 * insures the index has been given all the latest resource events.  This monitor
	 * may be canceled, but if it is the state of the index is not guaranteed to be
	 * consistent with the latest resource change events.</p>
	 * 
	 * @param monitor Used to report user readable progress as the manager insures the
	 * index is consistent with the latest resource events.  This monitor can be canceled
	 * to stop waiting for consistency but then no guaranty is made about the consistency
	 * of the index in relation to unprocessed resource changes
	 * 
	 * @return <code>true</code> if the wait finished successfully and the manager is consistent,
	 * <code>false</code> otherwise, either an error occurred while waiting for the manager
	 * or the monitor was canceled
	 * 
	 * @throws InterruptedException This can happen when waiting for other jobs
	 */
	public final boolean waitForConsistent(IProgressMonitor monitor) {
		boolean success = true;
		boolean interupted = false;
		SubMonitor progress = SubMonitor.convert(monitor);
		
		//set up the progress of waiting
		int remainingWork = 4;
		progress.beginTask(this.fMessage_Running,remainingWork);
		
		//wait for start up
		if(this.fStarting && !monitor.isCanceled()) {
			SubMonitor startingProgress = progress.newChild(1);
			startingProgress.subTask(this.fMessage_Initializing);
			while(this.fStarting && !monitor.isCanceled()) {
				//this creates a never ending progress that still moves forward
				startingProgress.setWorkRemaining(UNKNOWN_WORK);
				startingProgress.newChild(1).worked(1);
				try {
					Thread.sleep(WAIT_TIME);
				} catch (InterruptedException e) {
					interupted = true;
				}
			}
		}
		progress.setWorkRemaining(--remainingWork);
		
		//wait for workspace visiting job
		if(this.fWorkspaceVisitorJob != null && this.fWorkspaceVisitorJob.getState() != Job.NONE && !monitor.isCanceled()) {
			SubMonitor workspaceVisitorProgress = progress.newChild(1);
			workspaceVisitorProgress.subTask(this.fMessage_Initializing);
			while(this.fWorkspaceVisitorJob.getState() != Job.NONE && !monitor.isCanceled()) {
				//this creates a never ending progress that still moves forward
				workspaceVisitorProgress.setWorkRemaining(UNKNOWN_WORK);
				workspaceVisitorProgress.newChild(1).worked(1);
				try {
					Thread.sleep(WAIT_TIME);
				} catch (InterruptedException e) {
					interupted = true;
				}
			}
		}
		progress.setWorkRemaining(--remainingWork);
		
		//wait for the current resource event
		if(this.fResourceChangeListener.isProcessingEvents() && !monitor.isCanceled()) {
			SubMonitor workspaceVisitorProgress = progress.newChild(1);
			workspaceVisitorProgress.subTask(this.fMessage_Running);
			while(this.fResourceChangeListener.isProcessingEvents() && !monitor.isCanceled()) {
				workspaceVisitorProgress.setWorkRemaining(UNKNOWN_WORK);
				workspaceVisitorProgress.newChild(1).worked(1);
				try {
					this.fResourceChangeListener.waitForCurrentEvent(WAIT_TIME);
				} catch (InterruptedException e) {
					interupted = true;
				}
			}
		}
		progress.setWorkRemaining(--remainingWork);
		
		//wait for all files to be indexed
		if(this.fResourceEventProcessingJob.getNumResourceEventsToProcess() != 0 && !monitor.isCanceled()) {
			SubMonitor indexingProgress = progress.newChild(1);
			int prevNumResrouces;
			int numResources = this.fResourceEventProcessingJob.getNumResourceEventsToProcess();
			while(numResources != 0 && !monitor.isCanceled()) {
				//update the progress indicator
				indexingProgress.subTask(NLS.bind(this.fMessage_ProcessingFiles, "" + numResources)); //$NON-NLS-1$
				indexingProgress.setWorkRemaining(numResources);
				prevNumResrouces = numResources;
				numResources = this.fResourceEventProcessingJob.getNumResourceEventsToProcess();
				int numProcessed = prevNumResrouces - numResources;
				indexingProgress.worked(numProcessed > 0 ? numProcessed : 0);
				
				//give the index some time to do some indexing
				try {
					this.fResourceEventProcessingJob.waitForConsistant(WAIT_TIME);
				} catch (InterruptedException e) {
					interupted = true;
				}
			}
		}
		progress.setWorkRemaining(--remainingWork);
		
		if(monitor.isCanceled()) {
			success = false;
		}
		
		//reset the interrupted flag if we were interrupted
		if(interupted) {
			Thread.currentThread().interrupt();
		}
		
		return success;
	}
	
	/**
	 * <p>Called for each {@link IResource} given in a resource delta.  If the resource
	 * type is a file then used to determine if that file should be processed by the manager,
	 * if the resource type is a project or directory then it is used to determine if the children
	 * of the project or directory should be processed looking for file resources.</p>
	 * 
	 * <p><b>NOTE:</b> Even if <code>true</code> is returned for a directory resource that
	 * only means the children of the directory should be inspected for possible files to index.
	 * Directories themselves can not be managed in order to add to an index.</p>
	 * 
	 * @param type the {@link IResource#getType()} result of the resource to possibly index
	 * @param path the full {@link IPath} to the resource to possibly index
	 * @return <code>true</code> If the resource with the given <code>type</code> and
	 * <code>path</code> should either itself be indexed, or its children should be indexed,
	 * <code>false</code> if neither the described resource or any children should be indexed
	 */
	protected abstract boolean isResourceToIndex(int type, IPath path);
	
	/**
	 * <p>Called for each {@link ResourceEvent} gathered by the various sources and processed
	 * by the {@link ResourceEventProcessingJob}.  The implementation of this method
	 * should use the given information to update the index this manager is managing.</p>
	 * 
	 * @param source The source that reported this resource event
	 * @param action The action to be taken on the given <code>resource</code>
	 * @param resource The index should perform the given <code>action</code> on this
	 * resource
	 * @param movePath If the given <code>action</code> is {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM}
	 * or {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then this field will not be
	 * null and reports the path the given <code>resource</code> was either moved from or
	 * moved to respectively.
	 * 
	 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
	 * @see AbstractIndexManager#SOURCE_SAVED_STATE
	 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
	 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
	 * 
	 * @see AbstractIndexManager#ACTION_ADD
	 * @see AbstractIndexManager#ACTION_REMOVE
	 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
	 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
	 */
	protected abstract void performAction(byte source, byte action, IResource resource,
			IPath movePath);
	
	/**
	 * <p>Gets the working location of the manager. This is where any relevant
	 * state can be persisted.</p>
	 * 
	 * @return the working location of the manager
	 */
    protected abstract IPath getWorkingLocation();
	
	/**
	 * <p>Next time the manager starts up force a full workspace index</p>
	 */
	private void forceFullReIndexNextStart() {
		IPath reIndexPath =
			AbstractIndexManager.this.getWorkingLocation().append(RE_PROCESS_FILE_NAME);
		File file = new File(reIndexPath.toOSString());
		try {
			file.createNewFile();
		} catch (IOException e) {
			Logger.logException(this.fName + ": Could not create file to tell manager to" + //$NON-NLS-1$
					" do a full re-index on next load. " + //$NON-NLS-1$
					AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e);
		}
	}
	
	/**
	 * @return <code>true</code> if a full workspace index is needed as dictated by
	 * a previous call to {@link #forceFullReIndexNextStart()}, <code>false</code>
	 * otherwise
	 */
	private boolean isForcedFullReIndexNeeded() {
		boolean forcedFullReIndexNeeded = false;
		IPath reIndexPath =
			AbstractIndexManager.this.getWorkingLocation().append(RE_PROCESS_FILE_NAME);
		File file = new File(reIndexPath.toOSString());
		if(file.exists()) {
			file.delete();
			forcedFullReIndexNeeded = true;
		}
		
		return forcedFullReIndexNeeded;
	}
	
	/**
	 * <p>A system {@link Job} used to visit all of the files in the workspace
	 * looking for files to index.</p>
	 * 
	 * <p>This should only have to be done once per workspace on the first load,
	 * but if it fails or a SavedState can not be retrieved on a subsequent
	 * workspace load then this will have to be done again.</p>
	 */
	private class WorkspaceVisitorJob extends Job {
		/**
		 * <p>Default constructor that sets up this job as a system job</p>
		 */
		protected WorkspaceVisitorJob() {
			super(AbstractIndexManager.this.fMessage_Initializing);
			
			this.setUser(false);
			this.setSystem(true);
			this.setPriority(Job.LONG);
		}
		
		/**
		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
		 */
		protected IStatus run(IProgressMonitor monitor) {
			try {
				//update status
				monitor.beginTask(AbstractIndexManager.this.fMessage_Initializing,
						IProgressMonitor.UNKNOWN);
				
				//visit the workspace
				WorkspaceVisitor visitor = new WorkspaceVisitor(monitor);
				ResourcesPlugin.getWorkspace().getRoot().accept(visitor, IResource.NONE);
				
				//process any remaining batched up resources to index
				visitor.processBatchedResourceEvents();
			} catch(CoreException e) {
				Logger.logException(AbstractIndexManager.this.fName +
						": Failed visiting entire workspace for initial index. " + //$NON-NLS-1$
						AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e);
			}
			
			IStatus status;
			if(monitor.isCanceled()) {
				status = Status.CANCEL_STATUS;
			} else {
				status = Status.OK_STATUS;
			}
			
			return status;
		}
		
		/**
		 * <p>An {@link IResourceProxyVisitor} used to visit all of the files in the
		 * workspace looking for files to add to the index.</p>
		 * 
		 * <p><b>NOTE: </b>After this visitor is used {@link WorkspaceVisitor#processBatchedResourceEvents()
		 * must be called to flush out the last of the {@link ResourceEvent}s produced
		 * by this visitor.</p>
		 */
		private class WorkspaceVisitor implements IResourceProxyVisitor {
			/** {@link IProgressMonitor} used to report status and check for cancellation */
			private SubMonitor fProgress;
			
			/**
			 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
			 * <p>Map of resources events created and batched up by this visitor.
			 * These events are periodical be sent off to the
			 * {@link ResourceEventProcessingJob} but need to be sent off
			 * one final time after this visitor finishes it work.</p>
			 * 
			 * @see #processBatchedResourceEvents()
			 */
			private Map fBatchedResourceEvents;
			
			/**
			 * <p>Default constructor</p>
			 * @param monitor used to report status and allow this visitor to be canceled
			 */
			protected WorkspaceVisitor(IProgressMonitor monitor) {
				this.fProgress = SubMonitor.convert(monitor);
				this.fBatchedResourceEvents = new LinkedHashMap(BATCH_UP_AMOUNT);
			}

			/**
			 * <p>As long as the monitor is not canceled visit each file in the workspace
			 * that should be visited.</p>
			 * 
			 * @see org.eclipse.core.resources.IResourceProxyVisitor#visit(org.eclipse.core.resources.IResourceProxy)
			 * @see AbstractIndexManager#shouldVisit(String)
			 */
			public boolean visit(IResourceProxy proxy) throws CoreException {
				this.fProgress.subTask(proxy.getName());
				
				boolean visitChildren = false;
				
				/* if not canceled or a hidden resource then process file
				 * else don't visit children
				 */
				if(!this.fProgress.isCanceled()) {
					/* if root node always visit children
					 * else ask manager implementation if resource and its children should be visited 
					 */
					IPath path = proxy.requestFullPath();
					if(path.toString().equals("/")) { //$NON-NLS-1$
						visitChildren = true;
					} else if(isResourceToIndex(proxy.getType(), path)) {
						if(proxy.getType() == IResource.FILE) {
							//add the file to be indexed
							IFile file = (IFile) proxy.requestResource();
							if(file.exists()) {
								this.fBatchedResourceEvents.put(file, new ResourceEvent(
										AbstractIndexManager.SOURCE_WORKSPACE_SCAN,
										AbstractIndexManager.ACTION_ADD,
										null));
							}
						}
						visitChildren = true;
					}
				}
				
				//batch up resource changes before sending them out
				if(this.fBatchedResourceEvents.size() >= BATCH_UP_AMOUNT) {
					this.processBatchedResourceEvents();
				}
				
				return visitChildren;
			}
			
			/**
			 * <p>Sends any batched up resource events created by this visitor to the
			 * {@link ResourceEventProcessingJob}.<p>
			 * 
			 * <p><b>NOTE:</b> This will be called every so often as the visitor is
			 * visiting resources but needs to be called a final time by the user of
			 * this visitor to be sure the final events are sent off</p>
			 */
			protected void processBatchedResourceEvents() {
				AbstractIndexManager.this.fResourceEventProcessingJob.addResourceEvents(
						this.fBatchedResourceEvents);
				this.fBatchedResourceEvents.clear();
			}
		}
	}
	
	/**
	 * <p>Used to listen to resource change events in the workspace.  These events
	 * are batched up and then passed onto the {@link ResourceEventProcessingJob}.</p>
	 */
	private class ResourceChangeListener implements IResourceChangeListener {
		/**
		 * <p>The number of events currently being processed by this listener.</p>
		 * <p>Use the {@link #fEventsBeingProcessedLock} when reading or writing this field</p>
		 * 
		 * @see #fEventsBeingProcessedLock
		 */
		private volatile int fEventsBeingProcessed;
		
		/**
		 * Lock to use when reading or writing {@link #fEventsBeingProcessed}
		 * 
		 * @see #fEventsBeingProcessed
		 */
		private final Object fEventsBeingProcessedLock = new Object();
		
		/**
		 * <p>Current state of this listener</p>
		 * 
		 * @see AbstractIndexManager#STATE_DISABLED
		 * @see AbstractIndexManager#STATE_ENABLED
		 */
		private volatile byte fState;
		
		/**
		 * <p>Default constructor</p>
		 */
		protected ResourceChangeListener() {
			this.fState = STATE_DISABLED;
			this.fEventsBeingProcessed = 0;
		}
		
		/**
		 * <p>Start listening for resource change events</p>
		 */
		protected void start() {
			this.fState = STATE_ENABLED;
			ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
		}
		
		/**
		 * <p>Stop listening for resource change events and if already processing
		 * an event then wait for that processing to finish</p>
		 * 
		 * @throws InterruptedException waiting for a current event to finish processing
		 * could be interrupted
		 */
		protected void stop() throws InterruptedException {
			ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
			
			//wait indefinitely for current event to finish processing
			this.waitForCurrentEvent(0);
			
			this.fState = STATE_DISABLED;
		}
		
		/**
		 * <p>Blocks until either the current resource event has been processed or
		 * until the given timeout has passed.</p>
		 * 
		 * @param timeout block until either this timeout elapses (0 means never to timeout)
		 * or the current resource change event finishes being processed
		 * 
		 * @throws InterruptedException This can happen when waiting for a lock
		 */
		protected void waitForCurrentEvent(int timeout) throws InterruptedException {
			synchronized (this.fEventsBeingProcessedLock) {
				if(this.fEventsBeingProcessed != 0) {
					this.fEventsBeingProcessedLock.wait(timeout);
				}
			}
		}
		
		/**
		 * @return <code>true</code> if this listener is currently processing any
		 * events, <code>false</code> otherwise.
		 */
		protected boolean isProcessingEvents() {
			return this.fEventsBeingProcessed != 0;
		}
		
		/**
		 * <p>Process a resource change event.  If it is a pre-close or pre-delete then
		 * the {@link ResourceEventProcessingJob} is paused so it does not try to
		 * process resources that are about to be deleted.  The {@link ResourceDeltaVisitor}
		 * is used to actually process the event.</p>
		 * 
		 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
		 * @see ResourceDeltaVisitor
		 */
		public void resourceChanged(IResourceChangeEvent event) {
			try {
				//update the number of events being processed
				synchronized (this.fEventsBeingProcessedLock) {
					++this.fEventsBeingProcessed;
				}
				
				if(this.fState == STATE_ENABLED) {
					switch(event.getType()) {
						case IResourceChangeEvent.PRE_CLOSE:
						case IResourceChangeEvent.PRE_DELETE:{
							//pre-close or pre-delete pause the persister job so it does not interfere
							AbstractIndexManager.this.fResourceEventProcessingJob.pause();
							break;
						}
						case IResourceChangeEvent.POST_BUILD:
						case IResourceChangeEvent.POST_CHANGE: {
							//post change start up the indexer job and process the delta
							AbstractIndexManager.this.fResourceEventProcessingJob.unPause();
							
							// only analyze the full (starting at root) delta hierarchy
							IResourceDelta delta = event.getDelta();
							if (delta != null && delta.getFullPath().toString().equals("/")) { //$NON-NLS-1$
								try {
									//use visitor to visit all children
									ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(
											AbstractIndexManager.SOURCE_RESOURCE_CHANGE);
									delta.accept(visitor, false);
									
									//process any remaining batched up resources to index
									visitor.processBatchedResourceEvents();
								} catch (CoreException e) {
									Logger.logException(AbstractIndexManager.this.fName +
											": Failed visiting resrouce change delta. " + //$NON-NLS-1$
											AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e);
								}
							}
							break;
						}
					}
				} else {
					Logger.log(Logger.ERROR, "A resource change event came in after " + //$NON-NLS-1$
							AbstractIndexManager.this.fName + " shut down. This should never " + //$NON-NLS-1$
							"ever happen, but if it does the index may now be inconsistant."); //$NON-NLS-1$
				}
			} finally {
				//no matter how we exit be sure to update the number of events being processed
				synchronized (this.fEventsBeingProcessedLock) {
					--this.fEventsBeingProcessed;
					
					//if currently not events being processed, then notify
					if(this.fEventsBeingProcessed == 0) {
						this.fEventsBeingProcessedLock.notifyAll();
					}
				}
			}
		}
	}
	
	/**
	 * <p>Used to visit {@link IResourceDelta}s from both the {@link IResourceChangeListener}
	 * and from a {@link ISaveParticipant} given to {@link AbstractIndexManager#start(IResourceDelta, IProgressMonitor)}.
	 * The resource events are batched into groups of {@link AbstractIndexManager#BATCH_UP_AMOUNT}
	 * before being passed onto the {@link ResourceEventProcessingJob}.</p>
	 * 
	 * <p><b>NOTE 1: </b> This class is intended for one time use, thus a new instance should
	 * be instantiated each time this visitor is needed to process a new {@link IResourceDelta}.</p>
	 * 
	 * <p><b>NOTE 2: </b> Be sure to call {@link ResourceDeltaVisitor#processBatchedResourceEvents()}
	 * after using this visitor to be sure any remaining events get passed onto the
	 * {@link ResourceEventProcessingJob}.</p>
	 * 
	 * @see ResourceDeltaVisitor#processBatchedResourceEvents()
	 */
	private class ResourceDeltaVisitor implements IResourceDeltaVisitor {
		/** {@link IProgressMonitor} used to report status */
		private SubMonitor fProgress;
		
		/**
		 * <p>The source that should be used when sending resource events to the
		 * {@link ResourceEventProcessingJob}.</p>
		 * 
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 */
		private byte fSource;
		
		/**
		 * <p>Due to the nature of a visitor it has no way of knowing the total amount
		 * of work it has to do but it can start to predict it based on the number of
		 * children of each event it processes and whether it plans on visiting those
		 * children</p>
		 */
		private int fPredictedWorkRemaining;
		
		/**
		 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
		 * <p>Map of resources events created and batched up by this visitor.
		 * These events are periodical be sent off to the
		 * {@link ResourceEventProcessingJob} but need to be sent off
		 * one final time after this visitor finishes it work.</p>
		 * 
		 * @see #processBatchedResourceEvents()
		 */
		private Map fBatchedResourceEvents;
		
		/**
		 * <p>Creates a visitor that will create resource events based on the resources
		 * it visits and using the given source as the source of the events.</p>
		 * 
		 * @param source The source of the events that should be used when creating
		 * resource events from visited resources
		 * 
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 */
		protected ResourceDeltaVisitor(byte source) {
			this(SubMonitor.convert(null), source);
		}
		
		/**
		 * <p>Creates a visitor that will create resource events based on the resources
		 * it visits and using the given source as the source of the events and
		 * report its status to the given progress as best it can as it visits
		 * resources.</p>
		 * 
		 * <p><b>NOTE:</b> While the {@link SubMonitor} is provided to report status the
		 * visitor will not honor any cancellation requests.</p>
		 * 
		 * @param progress Used to report status. This visitor can <b>not</b> be
		 * canceled
		 * @param source The source of the events that should be used when creating
		 * resource events from visited resources
		 * 
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 */
		protected ResourceDeltaVisitor(SubMonitor progress, byte source) {
			this.fProgress = progress;
			this.fSource = source;
			this.fBatchedResourceEvents = new LinkedHashMap(BATCH_UP_AMOUNT);
			this.fPredictedWorkRemaining = 1;
		}
		
		/**
		 * <p>Transforms each {@link IResourceDelta} into a {@link ResourceEvent}.
		 * Batches up these {@link ResourceEvent}s and then passes them onto the
		 * {@link ResourceEventProcessingJob}.</p>
		 * 
		 * <p><b>NOTE 1: </b> Be sure to call {@link ResourceDeltaVisitor#processBatchedResourceEvents()}
		 * after using this visitor to be sure any remaining events get passed onto the
		 * {@link ResourceEventProcessingJob}.</p>
		 * 
		 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
		 * @see #processBatchedResourceEvents()
		 */
		public boolean visit(IResourceDelta delta) throws CoreException {
			//report status
			this.fProgress.subTask(
					NLS.bind(AbstractIndexManager.this.fMessage_ProcessingFiles,
							"" + fPredictedWorkRemaining, delta.getFullPath().toString())); //$NON-NLS-1$
			
			//process delta if resource not hidden
			boolean visitChildren = false;
			
			/* if root node always visit its children
			 * else ask manager implementation if resource and its children should be visited 
			 */
			if(delta.getFullPath().toString().equals("/")) { //$NON-NLS-1$
				visitChildren = true;
			} else {
				IResource resource = delta.getResource();
	
				//check if should index resource or its children
				if(isResourceToIndex(resource.getType(), resource.getFullPath())) {
					if(resource.getType() == IResource.FILE) {
					
						switch (delta.getKind()) {
							case IResourceDelta.CHANGED : {
								/* ignore any change that is not a CONTENT, REPLACED, TYPE,
								 * or MOVE_FROM change
								 */
								if( !((delta.getFlags() & IResourceDelta.CONTENT) != 0) &&
										!((delta.getFlags() & IResourceDelta.REPLACED) != 0) &&
										!((delta.getFlags() & IResourceDelta.TYPE) != 0) &&
										!(((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0))) {
									
									break;
								}
							}
							//$FALL-THROUGH$ it is intended that sometimes a change will fall through to add
							case IResourceDelta.ADDED : {
								if((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
									//create add move from action
									this.fBatchedResourceEvents.put(resource, new ResourceEvent(
											this.fSource,
											AbstractIndexManager.ACTION_ADD_MOVE_FROM,
											delta.getMovedFromPath()));
		
								} else {
									//create add action
									this.fBatchedResourceEvents.put(resource, new ResourceEvent(
											this.fSource,
											AbstractIndexManager.ACTION_ADD,
											null));
								}
								
								break;
							}
							case IResourceDelta.REMOVED : {
								if((delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
									//create remove move to action
									this.fBatchedResourceEvents.put(resource, new ResourceEvent(
											this.fSource,
											AbstractIndexManager.ACTION_REMOVE_MOVE_TO,
											delta.getMovedToPath()));
								} else {
									//create remove action
									this.fBatchedResourceEvents.put(resource, new ResourceEvent(
											this.fSource,
											AbstractIndexManager.ACTION_REMOVE,
											null));
								}
								break;
							}
						}
					}//end is file
					
					visitChildren = true;
				} else {
					visitChildren = false;
				}
					
				
				
				//deal with trying to report progress
				if(visitChildren) {
					this.fPredictedWorkRemaining += delta.getAffectedChildren().length;
				}
				this.fProgress.setWorkRemaining(this.fPredictedWorkRemaining);
				this.fProgress.worked(1);
				--this.fPredictedWorkRemaining;
				
				//batch up resource changes before sending them out
				if(this.fBatchedResourceEvents.size() >= BATCH_UP_AMOUNT) {
					this.processBatchedResourceEvents();
				}
			}
			
			return visitChildren;
		}
		
		/**
		 * <p>Sends any batched up resource events created by this visitor to the
		 * {@link ResourceEventProcessingJob}.<p>
		 * 
		 * <p><b>NOTE:</b> This will be called every so often as the visitor is
		 * visiting resources but needs to be called a final time by the user of
		 * this visitor to be sure the final events are sent off</p>
		 */
		protected void processBatchedResourceEvents() {
			AbstractIndexManager.this.fResourceEventProcessingJob.addResourceEvents(
					this.fBatchedResourceEvents);
			this.fBatchedResourceEvents.clear();
		}
	}
	
	/**
	 * <p>Collects {@link ResourceEvent}s from the different sources and then processes
	 * each one by calling {@link AbstractIndexManager#performAction(byte, byte, IResource, IPath)}
	 * for each {@link ResourceEvent}.</p>
	 * 
	 * @see AbstractIndexManager#performAction(byte, byte, IResource, IPath)
	 */
	private class ResourceEventProcessingJob extends Job {
		/** Length to delay when scheduling job */
		private static final int DELAY = 500;
		
		/**
		 * <p>Name of the file where resource events still to index
		 * will be preserved for the next start up.</p>
		 */
		private static final String PRESERVED_RESOURCE_EVENTS_TO_PROCESS_FILE_NAME = ".preservedResourceEvents";  //$NON-NLS-1$
		
		/**
		 * <p>This needs to be updated if {@link #preserveReceivedResourceEvents()} ever
		 * changes how it persists resource events so that {@link #loadPreservedReceivedResourceEvents(SubMonitor)}
		 * knows when opening a file that the format is of the current version and if not
		 * knows it does not know how to read the older version.</p>
		 * 
		 * @see #preserveReceivedResourceEvents()
		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
		 */
		private static final long serialVersionUID = 1L;
		
		/** Whether this job has been paused or not */
		private volatile boolean fIsPaused;
		
		/**
		 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
		 * <p>The list of resources events to be processed</p>
		 */
		private Map fResourceEvents;
		
		/** Lock used when accessing {@link #fBatchedResourceEvents} */
		private final Object fResourceEventsLock = new Object();
		
		/**
		 * Locked used for allowing other jobs to wait on this job.  This job
		 * will notify those waiting on this lock whenever it is done processing
		 * all resource events it currently knows about.
		 * 
		 * @see #waitForConsistant(int)
		 */
		private final Object fToNotifyLock = new Object();
		
		/**
		 * <p>Sets up this job as a long running system job</p>
		 */
		protected ResourceEventProcessingJob() {
			super(AbstractIndexManager.this.fMessage_Running);
			
			//set this up as a long running system job
			this.setUser(false);
			this.setSystem(true);
			this.setPriority(Job.LONG);
			
			this.fIsPaused = false;
			this.fResourceEvents = new LinkedHashMap();
		}
		
		/**
		 * <p>Loads any preserved {@link ResourceEvent}s from the last time {@link #stop(boolean)}
		 * was invoked and schedules the job to be run</p>
		 * 
		 * <p><b>NOTE: </b>Should be used instead of of calling {@link Job#schedule()}
		 * because this method also takes care of loading preserved state.</p>
		 * 
		 * @param loadPreservedResourceEvents <code>true</code> if should load any
		 * preserved {@link ResourceEvent}s from the last time {@link #stop(boolean)}
		 * was invoked
		 * 
		 * @return <code>true</code> if either <code>loadPreservedResourceEvents</code>
		 * was false or there was success in loading the preserved {@link ResourceEvent}s.
		 * If <code>false</code> then some {@link ResourceEvent}s may have been loosed
		 * and to insure index consistency with the workspace a full workspace  re-index
		 * is needed.
		 * 
		 * @see #stop(boolean)
		 */
		protected synchronized boolean start(boolean loadPreservedResourceEvents, 
				SubMonitor progress) {
			
			boolean successLoadingPreserved = true;
			
			//attempt to load preserved resource events if requested
			if(!loadPreservedResourceEvents) {
				File preservedResourceEventsFile = this.getPreservedResourceEventsFile();
				preservedResourceEventsFile.delete();
			} else {
				successLoadingPreserved = this.loadPreservedReceivedResourceEvents(progress);
			}
			
			//start up the job
			this.schedule();
			
			return successLoadingPreserved;
		}
		
		/**
		 * <p>Immediately stops the job and preserves any {@link ResourceEvent}s in the queue
		 * to be processed by not yet processed if requested</p>
		 * 
		 * @param preserveResourceEvents <code>true</code> to preserve any {@link ResourceEvent}s
		 * in the queue yet to be processed, <code>false</code> otherwise
		 * 
		 * @return <code>true</code> if either <code>preserveResourceEvents</code> is 
		 * <code>false</code> or if there was success in preserving the {@link ResourceEvent}s
		 * yet to be processed.  If <code>false</code> then the preserving failed and a
		 * full workspace re-processing is needed the next time the manager is started
		 * 
		 * @throws InterruptedException This could happen when trying to cancel or join 
		 * the job in progress, but it really shouldn't
		 * 
		 * @see #start(boolean, SubMonitor)
		 */
		protected synchronized boolean stop(boolean preserveResourceEvents) throws InterruptedException {
			//this will not block indefinitely because it is known this job can be canceled
			this.cancel();
			this.join();
			
			//preserve if requested, else be sure no preserve file is left over for next start
			boolean success = true;
			if(preserveResourceEvents && this.hasResourceEventsToProcess()) {
				success = this.preserveReceivedResourceEvents();
			} else {
				this.getPreservedResourceEventsFile().delete();
			}
			
			return success;
		}
		
		/**
		 * @return <code>true</code> if job is currently running or paused
		 * 
		 * @see #pause()
		 * @see #unPause()
		 */
		protected synchronized boolean isProcessing() {
			return this.getState() != Job.NONE || this.fIsPaused;
		}
		
		/**
		 * <p>Un-pauses this job.  This has no effect if the job is already running.</p>
		 * <p>This should be used in place of {@link Job#schedule()} to reset state
		 * caused by calling {@link #pause()}</p>
		 * 
		 * @see #pause()
		 */
		protected synchronized void unPause() {
			this.fIsPaused = false;
			
			//get the job running again depending on its current state
			if(this.getState() == Job.SLEEPING) {
				this.wakeUp(DELAY);
			} else {
				this.schedule(DELAY);
			}
		}
		
		/**
		 * <p>Pauses this job, even if it is running</p>
		 * <p>This should be used in place of {@link Job#sleep()} because {@link Job#sleep()}
		 * will not pause a job that is already running but calling this will pause this job
		 * even if it is running. {@link #unPause()} must be used to start this job again</p>
		 * 
		 * @see #unPause()
		 */
		protected synchronized void pause() {
			//if job is already running this will force it to pause
			this.fIsPaused = true;
			
			//this only works if the job is not running
			this.sleep();
		}
		
		/**
		 * <p>Adds a batch of {@link ResourceEvent}s to the queue of events to be processed.
		 * Will also un-pause the job if it is not already running</p>
		 * 
		 * @param resourceEvents {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
		 * A batch of {@link ResourceEvent}s to be processed
		 * 
		 * @see #addResourceEvent(ResourceEvent)
		 * @see #unPause()
		 */
		protected void addResourceEvents(Map resourceEvents) {
			Iterator iter = resourceEvents.keySet().iterator();
			while(iter.hasNext()) {
				IResource resource = (IResource)iter.next();
				ResourceEvent resourceEvent = (ResourceEvent)resourceEvents.get(resource);
				addResourceEvent(resource, resourceEvent);
			}
			
			//un-pause the processor if it is not already running
			if(!isProcessing()) {
				this.unPause();
			}
		}
		
		/**
		 * <p>Gets the number of {@link ResourceEvent}s left to process by this job. This
		 * count is only valid for the exact moment it is returned because events are
		 * constantly being added and removed from the queue of events to process</p>
		 * 
		 * @return the number of {@link ResourceEvent}s left to process
		 */
		protected int getNumResourceEventsToProcess() {
			return this.fResourceEvents.size();
		}
		
		/**
		 * <p>Blocks until either the given timeout elapses (0 means never to timeout), or
		 * there are currently no {@link ResourceEvent}s to process or being processed
		 * by this job</p>
		 * 
		 * @param timeout block until either this timeout elapses (0 means never to timeout)
		 * or there are currently no {@link ResourceEvent}s to process or being processed
		 * by this job
		 * 
		 * @throws InterruptedException This can happen when waiting for a lock
		 */
		protected void waitForConsistant(int timeout) throws InterruptedException {
			if(hasResourceEventsToProcess() || isProcessing()) {
				synchronized (this.fToNotifyLock) {
					this.fToNotifyLock.wait(timeout);
				}
			}
		}
		
		/**
		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
		 */
		protected IStatus run(IProgressMonitor monitor) {
			try {
				//report status
				SubMonitor progress = SubMonitor.convert(monitor);
				
				while(!this.fIsPaused && !monitor.isCanceled() && this.hasResourceEventsToProcess()) {
					//report status
					progress.setTaskName(NLS.bind(AbstractIndexManager.this.fMessage_ProcessingFiles,
									"" + getNumResourceEventsToProcess())); //$NON-NLS-1$
					progress.setWorkRemaining(getNumResourceEventsToProcess());
					
					//get the next event to process
					ResourceEvent resourceEvent = null;
					IResource resource = null;
					synchronized (this.fResourceEventsLock) {
						resource = (IResource) this.fResourceEvents.keySet().iterator().next();
						resourceEvent = (ResourceEvent)this.fResourceEvents.remove(resource);
					}
					
					//report status
					monitor.subTask(resource.getName());
					
					//perform action safely
					final byte source = resourceEvent.fSource;
					final byte action = resourceEvent.fAction;
					final IResource finResource = resource;
					final IPath movePath = resourceEvent.fMovePath;
					SafeRunner.run(new ISafeRunnable() {
						public void run() throws Exception {
							AbstractIndexManager.this.performAction(source, action,
									finResource, movePath);
						}
	
						public void handleException(Throwable e) {
							Logger.logException("Error while performing an update to the index. " + //$NON-NLS-1$
									AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e);
						}
					});
					
					//report progress
					progress.worked(1);
					
					//avoid dead locks
					Job.getJobManager().currentJob().yieldRule(monitor);
				}
				
				//done work
				monitor.done();
			} finally {
				//want to be sure we notify no matter how we exit
				this.notifyIfConsistant();
			}
			
			/* if canceled then return CANCEL,
			 * else if done or paused return OK
			 */
			IStatus exitStatus;
			if(monitor.isCanceled()) {
				exitStatus = Status.CANCEL_STATUS;
			} else {
				exitStatus = Status.OK_STATUS;
			}
			
			return exitStatus;
		}
		
		/**
		 * <p>If resource not already scheduled to be processed, schedule it
		 * else if resource already scheduled to be processed, update the action only if
		 * the new action comes from a resource change event.</p>
		 * 
		 * <p>Ignore other sources for updating existing resource events because all other
		 * sources are "start-up" type sources and thus only {@link ResourceEvent} with a
		 * source of a resource change event trump existing events.</p>
		 * 
		 * @param resourceEvent {@link ResourceEvent} to be processed by this job
		 */
		private void addResourceEvent(IResource resource, ResourceEvent resourceEvent) {
			
			synchronized (this.fResourceEventsLock) {
				/* if resource not already scheduled to be processed, schedule it
				 * else if resource already scheduled to be processed, update the action only if
				 * 		the new action comes from a resource change event
				 */
				if(!this.fResourceEvents.containsKey(resource)) {
					this.fResourceEvents.put(resource, resourceEvent);
				} else if(resourceEvent.fSource == AbstractIndexManager.SOURCE_RESOURCE_CHANGE) {
					((ResourceEvent)this.fResourceEvents.get(resource)).fAction = resourceEvent.fAction;
				} else {
					//Purposely ignoring all other resource events
				}
			}
		}
		
		/**
		 * @return <code>true</code> if there are any resources to process,
		 * <code>false</code> otherwise
		 */
		private boolean hasResourceEventsToProcess() {
			return !this.fResourceEvents.isEmpty();
		}
		
		/**
		 * <p>Preserves all of the resource events that have been received by this
		 * manager but not yet processed</p>
		 * 
		 * <p>If this operation was successful then the next time the manager starts
		 * it can load these events and process them.  If it was not successful then a
		 * full re-processing of the entire workspace will need to take place to be
		 * sure the index is consistent.</p>
		 * 
		 * <p><b>NOTE:</b> If this method changes how it preserves these events then
		 * {@link #serialVersionUID} will need to be incremented so that the manager
		 * does not attempt to load an old version of the file that may exist in a users
		 * workspace.  Also {@link #loadPreservedReceivedResourceEvents(SubMonitor)} will
		 * have to be updated to load the new file structure.</p>
		 * 
		 * @return <code>true</code> if successfully preserved the resource events that
		 * have been received by not yet processed, <code>false</code> otherwise
		 * 
		 * @see #serialVersionUID
		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
		 */
		private boolean preserveReceivedResourceEvents() {
			File preservedResourceEventsFile = this.getPreservedResourceEventsFile();
			boolean success = true;
			
			synchronized (this.fResourceEventsLock) {
				DataOutputStream dos = null;
				try {
					//if file already exists delete it
					if(preservedResourceEventsFile.exists()) {
						preservedResourceEventsFile.delete();
						preservedResourceEventsFile.createNewFile();
					}
					
					//create output objects
					FileOutputStream fos = new FileOutputStream(preservedResourceEventsFile);
					BufferedOutputStream bos = new BufferedOutputStream(fos);
					dos = new DataOutputStream(bos);
					
					//write serial version
					dos.writeLong(serialVersionUID);
					
					//write size
					dos.writeInt(this.getNumResourceEventsToProcess());
					
					//write out all the information needed to restore the resource events to process
					Iterator iter = this.fResourceEvents.keySet().iterator();
					while(iter.hasNext()) {
						IResource resource = (IResource)iter.next();
						ResourceEvent resourceEvent = (ResourceEvent)this.fResourceEvents.get(resource);
						
						if(resourceEvent.fSource != AbstractIndexManager.SOURCE_WORKSPACE_SCAN) {
							//write out information
							dos.writeByte(resourceEvent.fAction);
							dos.writeByte(resource.getType());
							byte[] pathBytes = resource.getFullPath().toString().getBytes(ENCODING_UTF16);
							dos.write(pathBytes);
							dos.writeByte('\0');
							if(resourceEvent.fMovePath != null) {
								dos.writeBytes(resourceEvent.fMovePath.toPortableString());
							}
							dos.writeByte('\0');
						}
					}
					
					this.fResourceEvents.clear();
					
					dos.flush();
				} catch (FileNotFoundException e) {
					Logger.logException(AbstractIndexManager.this.fName +
							": Exception while opening file to preserve resrouces to index.", //$NON-NLS-1$
							e);
					success = false;
				} catch (IOException e) {
					Logger.logException(AbstractIndexManager.this.fName +
							": Exception while writing to file to preserve resrouces to index.", //$NON-NLS-1$
							e);
					success = false;
				} finally {
					//be sure to close output
					if(dos != null) {
						try {
							dos.close();
						} catch (IOException e) {
							Logger.logException(AbstractIndexManager.this.fName +
									": Exception while closing file with preserved resources to index.", //$NON-NLS-1$
									e);
							success = false;
						}
					}
				}
				
				//if failed, for consistency must do a full re-process next workspace load
				if(!success) {
					preservedResourceEventsFile.delete();
				}
			}
			
			return success;
		}
		
		/**
		 * <p>Loads the received resource events that were preserved during the manager's
		 * last shut down so they can be processed now</p>
		 * 
		 * <p>If this operation is not successful then a full re-processing of the
		 * entire workspace is needed to be sure the index is consistent.</p>
		 * 
		 * @param progress used to report status of loading the preserved received resource events
		 * @return <code>true</code> if the loading of the preserved received resource events
		 * was successful, <code>false</code> otherwise.
		 * 
		 * @see #serialVersionUID
		 * @see #preserveReceivedResourceEvents()
		 */
		private boolean loadPreservedReceivedResourceEvents(SubMonitor progress) {
			progress.subTask(AbstractIndexManager.this.fMessage_Initializing);
			
			boolean success = true;
			File preservedResourceEventsFile = this.getPreservedResourceEventsFile();
			
			if(preservedResourceEventsFile.exists()) {
				Map preservedResourceEvents = null;
				
				DataInputStream dis = null;
				try {
					FileInputStream fis = new FileInputStream(preservedResourceEventsFile);
					BufferedInputStream bis = new BufferedInputStream(fis);
					dis = new DataInputStream(bis);
					
					//check serial version first
					long preservedSerialVersionUID = dis.readLong();
					if(preservedSerialVersionUID == serialVersionUID) {
						
						//read each record
						int numberOfRecords = dis.readInt();
						preservedResourceEvents = new LinkedHashMap(numberOfRecords);
						progress.setWorkRemaining(numberOfRecords);
						for(int i = 0; i < numberOfRecords; ++i) {
							//action is first byte
							byte action = dis.readByte();
							
							//file type is the next byte 
							byte fileType = dis.readByte();
							
							//resource location are the next bytes
							ByteArrayOutputStream resourceLocoationBOS = new ByteArrayOutputStream();
							byte b = dis.readByte();
							while(b != '\0') {
								resourceLocoationBOS.write(b);
								b = dis.readByte();
							}
							
							//move path are the next bytes
							ByteArrayOutputStream movePathBOS = new ByteArrayOutputStream();
							b = dis.readByte();
							while(b != '\0') {
								movePathBOS.write(b);
								b = dis.readByte();
							}
							
							//get the resource
							IResource resource = null;
							IPath resourcePath = new Path(new String(resourceLocoationBOS.toByteArray(), ENCODING_UTF16));
							if(fileType == IResource.FILE) {
								resource =
									ResourcesPlugin.getWorkspace().getRoot().getFile(resourcePath);
							} else {
								resource =
									ResourcesPlugin.getWorkspace().getRoot().getFolder(resourcePath);
							}
							
							//get the move path
							IPath movePath = null;
							if(movePathBOS.size() != 0) {
								movePath = new Path(new String(movePathBOS.toByteArray(), ENCODING_UTF16));
							}
							
							//add the object to the list of of preserved resources
							preservedResourceEvents.put(resource, new ResourceEvent(
									AbstractIndexManager.SOURCE_PRESERVED_RESOURCES_TO_INDEX,
									action, movePath));
							
							progress.worked(1);
						}	
					} else {
						success = false;
					}
				} catch (FileNotFoundException e) {
					Logger.logException(AbstractIndexManager.this.fName +
							": Exception while opening file to read preserved resources to index.", //$NON-NLS-1$
							e);
					success = false;
				} catch (IOException e) {
					Logger.logException(AbstractIndexManager.this.fName +
							": Exception while reading from file of preserved resources to index.", //$NON-NLS-1$
							e);
					success = false;
				} finally {
					if(dis != null) {
						try {
							dis.close();
						} catch (IOException e) {
							Logger.logException(AbstractIndexManager.this.fName +
									": Exception while closing file of preserved resources" + //$NON-NLS-1$
									" to index that was just read.  This should have no" + //$NON-NLS-1$
									" effect on the consistency of the index.", //$NON-NLS-1$
									e);
						}
					}
				}
				
				//if success loading preserved then add to master list
				if(success) {
					synchronized (this.fResourceEventsLock) {
						Iterator iter = preservedResourceEvents.keySet().iterator();
						while(iter.hasNext()) {
							IResource resource = (IResource)iter.next();
							ResourceEvent event = (ResourceEvent)preservedResourceEvents.get(resource);
							this.fResourceEvents.put(resource, event);
						}
					}
				} else {
					//failed reading file, so delete it
					preservedResourceEventsFile.delete();
				}
			}
			
			return success;
		}
		
		/**
		 * @return {@link File} that contains any resource events received but not processed
		 * by this manager the last time it shutdown. This file may or may not actually
		 * exist.
		 * 
		 * @see #preserveReceivedResourceEvents()
		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
		 */
		private File getPreservedResourceEventsFile() {
			IPath preservedResroucesToIndexPath =
				AbstractIndexManager.this.getWorkingLocation().append(
						PRESERVED_RESOURCE_EVENTS_TO_PROCESS_FILE_NAME);
			return new File(preservedResroucesToIndexPath.toOSString());
		}
		
		/**
		 * <p>If all resource events have been processed 
		 */
		private void notifyIfConsistant() {
			if(!this.hasResourceEventsToProcess()) {
				synchronized (this.fToNotifyLock) {
					this.fToNotifyLock.notifyAll();
				}
			}
		}
	}
	
	/**
	 * <p>Represents a resource that was discovered by this manager.  Contains
	 * all the information this manager and the index needs to know about this
	 * resource.  Such has how the manager was notified about this resource and
	 * the type of action occurring on the resource.</p>
	 */
	private static class ResourceEvent {
		/**
		 * <p>The source of this resource event</p>
		 * 
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
		 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
		 */
		protected byte fSource;
		
		/**
		 * <p>The action that the index should take with this resource</p>
		 *
		 * @see AbstractIndexManager#ACTION_ADD
		 * @see AbstractIndexManager#ACTION_REMOVE
		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
		 */
		protected byte fAction;
		
		/**
		 * 
		 * <p>If the {@link #fAction} is {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM} or
		 * {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then this field will have the
		 * path the resource was moved from or moved to. Else this field will be <code>null</code></p>
		 * 
		 * <p><b>NOTE: </b>Maybe <code>null</code>.</p>
		 * 
		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
		 */
		protected IPath fMovePath;
		
		/**
		 * <p>Creates a resource event that the index needs to react to in some way</p>
		 * 
		 * @param source source that the manager used to learn of this resource
		 * @param action action the index should take on this resource
		 * @param resource resource that the index should know about
		 * @param movePath if action is {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM} or
		 * {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then this should be the path the
		 * resource was moved from or moved to respectively, else should be <code>null</code>
		 * 
		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
		 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
		 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
		 * 
		 * @see AbstractIndexManager#ACTION_ADD
		 * @see AbstractIndexManager#ACTION_REMOVE
		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
		 */
		protected ResourceEvent(byte source, byte action, IPath movePath) {
			this.fSource = source;
			this.fAction = action;
			this.fMovePath = movePath;
		}
	}
}