[247859] Order of the validationStarting/Finishing(null) calls is still wrong
diff --git a/plugins/org.eclipse.wst.validation/.options b/plugins/org.eclipse.wst.validation/.options
index 5c38488..404c71b 100644
--- a/plugins/org.eclipse.wst.validation/.options
+++ b/plugins/org.eclipse.wst.validation/.options
@@ -29,3 +29,9 @@
 # As an example, you could use this plug-in id for a v1 validator: org.eclipse.jst.j2ee.ejb.EJBValidator
 # and org.eclipse.wst.html.ui.HTMLValidator for a v2 validator
 org.eclipse.wst.validation/filter/allExcept=
+
+# The tracing level. If not supplied a default of zero is used. The higher the number the
+# more verbose the tracing.
+org.eclipse.wst.validation/trace/level=
+
+
diff --git a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/FilterUtil.java b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/FilterUtil.java
index fb2a80d..39a36bc 100644
--- a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/FilterUtil.java
+++ b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/FilterUtil.java
@@ -613,7 +613,7 @@
 
 					IResource resource = subdelta.getResource();
 
-					if (Tracing.isLogging()) {
+					if (Tracing.isLogging(2)) {
 						StringBuffer buffer = new StringBuffer("FilterUtil-01: subdelta of "); //$NON-NLS-1$
 						buffer.append(resource.getName());
 						buffer.append(" has resource delta kind: "); //$NON-NLS-1$
diff --git a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationBuilder.java b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationBuilder.java
index 824aace..c88a1fe 100644
--- a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationBuilder.java
+++ b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationBuilder.java
@@ -30,9 +30,9 @@
 import org.eclipse.wst.validation.internal.ProjectConfiguration;
 import org.eclipse.wst.validation.internal.ResourceConstants;
 import org.eclipse.wst.validation.internal.ResourceHandler;
+import org.eclipse.wst.validation.internal.Tracing;
 import org.eclipse.wst.validation.internal.ValBuilderJob;
 import org.eclipse.wst.validation.internal.ValManager;
-import org.eclipse.wst.validation.internal.ValOperationManager;
 import org.eclipse.wst.validation.internal.ValidatorMetaData;
 import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;
 
@@ -62,8 +62,14 @@
 	protected List<IProject> referencedProjects;
 	protected IWorkbenchContext workbenchContext = null;
 	
-	/** All the jobs that the validation framework spawns will belong to this family. */
+	/** 
+	 * All the jobs that the validation framework spawns (except for the FamilyValidationFinishedJob) 
+	 * will belong to this family. 
+	 */
 	public static final Object FAMILY_VALIDATION_JOB = new Object();
+	
+	/** The job that waits to issue the final clean up. */
+	public static final Object FamilyValidationFinishedJob = new Object();
 
 	public ValidationBuilder() {
 	}
@@ -109,8 +115,10 @@
 	}
 
 	protected void clean(IProgressMonitor monitor) throws CoreException {
-		newClean(monitor);
 		IProject currentProject = getProject();
+		Tracing.log("ValidationBuilder-02 clean ", currentProject); //$NON-NLS-1$
+
+		newClean(monitor);
 		if (currentProject == null || !currentProject.isAccessible())return;
 		try {
 			ProjectConfiguration prjp = ConfigurationManager.getManager().getProjectConfiguration(currentProject);
@@ -138,6 +146,11 @@
 	public IProject[] build(int kind, Map parameters, IProgressMonitor monitor) {
 		IResourceDelta delta = null;
 		IProject project = getProject();
+		Tracing.log("ValidationBuilder-01 build ", kind, project);  //$NON-NLS-1$
+		if (Tracing.isLogging(1)){
+			Tracing.logResourceDeltas(getDelta(project), 50);
+		}
+		
 		// GRK I wonder why this builder needs to know about all the other referenced projects?
 		// won't they have builders of their own.
 		IProject[] referenced = getAllReferencedProjects(project, null);
@@ -279,7 +292,7 @@
 				break;
 		}
 		
-		ValBuilderJob.validateProject(project, delta, kind, ValOperationManager.getDefault().getOperation());		
+		ValBuilderJob.validateProject(project, delta, kind);		
 	}
 	
 	
diff --git a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationOperation.java b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationOperation.java
index 176a83c..045be17 100644
--- a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationOperation.java
+++ b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationOperation.java
@@ -85,8 +85,9 @@
 	
 	private static final int jobsPerProcessor = 3;
 	
-	private static class ValidationLauncherJob extends Job {
-	    private Queue<Job> validationJobs = new LinkedList<Job>();
+	private final static class ValidationLauncherJob extends Job {
+	    private Queue<Job> _validationJobs = new LinkedList<Job>();
+	    
 	    public ValidationLauncherJob() {
             super(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_VALIDATION_JOB_MSG));
             setSystem(true);
@@ -96,10 +97,10 @@
 	    protected IStatus run(IProgressMonitor monitor) {
 			int processors = Runtime.getRuntime().availableProcessors();
 			int totalInitialJobs = processors * jobsPerProcessor;
-    		synchronized (validationJobs) {
+    		synchronized (_validationJobs) {
     			// never schedule more than 3 validation jobs per processor at a time
     			for (int i=0; i< totalInitialJobs; i++) {
-    				Job validationJob = validationJobs.poll();
+    				Job validationJob = _validationJobs.poll();
     				if (validationJob == null) break;
     				addJobChangeAdapter(validationJob);
     				validationJob.schedule();
@@ -112,8 +113,8 @@
 	    	job.addJobChangeListener(new JobChangeAdapter(){
 	    		// when done, see if there is another validation job to schedule
 				public void done(IJobChangeEvent event) {
-					synchronized (validationJobs) {
-						Job validationJob = validationJobs.poll();
+					synchronized (_validationJobs) {
+						Job validationJob = _validationJobs.poll();
 						if (validationJob != null) {
 							addJobChangeAdapter(validationJob);
 							validationJob.schedule();
@@ -133,10 +134,10 @@
 	    }
 	    
 	    public void addValidationJob(Job validationJob) {
-	    	synchronized (validationJobs) {
-	    		validationJobs.add(validationJob);
+	    	synchronized (_validationJobs) {
+	    		_validationJobs.add(validationJob);
 	    		// schedule the job if we were empty
-	    		if (validationJobs.size() == 1) {
+	    		if (_validationJobs.size() == 1) {
 	    			this.schedule();
 	    		}
 	    	}
@@ -1263,12 +1264,17 @@
 	 * (hProject.getName().indexOf("fork") > -1)) { Thread.dumpStack(); } System.err.println(prefix +
 	 * "End ValidationOperation"); }
 	 */
+	
+	/**
+	 * @deprecated This class is no longer used by the framework.
+	 */
 	public class ProjectRunnable implements Runnable {
 		private WorkbenchReporter _reporter;
 		private IValidator _validator;
 		private ValidatorMetaData _vmd;
 		private IFileDelta[] _delta;
 
+		@SuppressWarnings("unchecked")
 		public ProjectRunnable(WorkbenchReporter reporter, IValidator validator, 
 			ValidatorMetaData vmd, IWorkbenchContext helper, IFileDelta[] delta, Iterator iterator) {
 			_reporter = reporter;
diff --git a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/plugin/ValidationPlugin.java b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/plugin/ValidationPlugin.java
index f7f7d7b..5a6ece7 100644
--- a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/plugin/ValidationPlugin.java
+++ b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/plugin/ValidationPlugin.java
@@ -23,7 +23,6 @@
 import org.eclipse.wst.validation.internal.ProjectUnavailableError;
 import org.eclipse.wst.validation.internal.ResourceUnavailableError;
 import org.eclipse.wst.validation.internal.Tracing;
-import org.eclipse.wst.validation.internal.ValOperationManager;
 import org.eclipse.wst.validation.internal.core.Message;
 import org.eclipse.wst.validation.internal.provisional.core.IMessage;
 import org.osgi.framework.Bundle;
@@ -100,15 +99,15 @@
 		DependencyIndex di = (DependencyIndex)ValidationFramework.getDefault().getDependencyIndex();
 		IWorkspace ws = ResourcesPlugin.getWorkspace();
 		ws.addSaveParticipant(this, di);
-		ws.addResourceChangeListener(ValOperationManager.getDefault(), 
-			IResourceChangeEvent.POST_BUILD | IResourceChangeEvent.PRE_BUILD);
+//		ws.addResourceChangeListener(ValOperationManager.getDefault(), 
+//			IResourceChangeEvent.POST_BUILD | IResourceChangeEvent.PRE_BUILD);
 
 	}
 
 	public void stop(BundleContext context) throws Exception {
 		super.stop(context);
 		ResourcesPlugin.getWorkspace().removeResourceChangeListener( EventManager.getManager() );		
-		ResourcesPlugin.getWorkspace().removeResourceChangeListener( ValOperationManager.getDefault() );		
+//		ResourcesPlugin.getWorkspace().removeResourceChangeListener( ValOperationManager.getDefault() );		
 		EventManager.getManager().shutdown();
 	}
 
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResult.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResult.java
index 1e54b7c..c1714e1 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResult.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResult.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * Copyright (c) 2007, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -34,9 +34,9 @@
  */
 public final class ValidationResult {
 	
-	private List<ValidatorMessage> _messages;
+	private final List<ValidatorMessage> _messages = new LinkedList<ValidatorMessage>();
 	
-	private static ValidatorMessage[] _noMessages = new ValidatorMessage[0];
+	private final static ValidatorMessage[] _noMessages = new ValidatorMessage[0];
 	
 	private boolean		_canceled;
 	
@@ -78,12 +78,14 @@
 	 * one type of message, and those messages can be either be directly used by
 	 * the caller, or automatically converted into IMarkers by the validation
 	 * framework.
+	 * </p>
 	 * <p>
 	 * To make matters even more complicated there is a third way to return
 	 * messages. To make it easier for old validators to port to the new
 	 * framework, they can continue to use an IReporter. If a validator calls
 	 * the getReporter() method then it is assumed by the framework that that is
 	 * the approach that they have chosen.
+	 * </p>
 	 * 
 	 * @see #getReporter(IProgressMonitor)
 	 * 
@@ -91,7 +93,7 @@
 	 * 		A validation message.
 	 */
 	public void add(ValidatorMessage message){
-		getMessageList().add(message);
+		_messages.add(message);
 	}
 	
 	/**
@@ -163,6 +165,19 @@
 		_messages.toArray(msgs);
 		return msgs;
 	}
+		
+	/**
+	 * Answer a copy of any validation messages that were added by the validator. The array is a new
+	 * array, and each message is a copy. 
+	 * @return an array is returned even if there are no messages.
+	 */
+	public synchronized ValidatorMessage[] getMessagesAsCopy(){
+		if (_messages == null)return _noMessages;
+		ValidatorMessage[] msgs = new ValidatorMessage[_messages.size()];
+		int i = 0;
+		for (ValidatorMessage msg : _messages)msgs[i++] = msg.asCopy();
+		return msgs;
+	}
 
 	/**
 	 * Update the resources that the validated resource depends on. This can be
@@ -179,11 +194,6 @@
 		_dependsOn = dependsOn;
 	}
 	
-	private List<ValidatorMessage> getMessageList(){
-		if (_messages == null)_messages = new LinkedList<ValidatorMessage>();
-		return _messages;
-	}
-
 	/**
 	 * @return All the resources that were validated as a side-effect of
 	 * 	validating the main resource, or null if none were.
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResults.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResults.java
index c32d273..ba947f8 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResults.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResults.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007 IBM Corporation and others.
+ * Copyright (c) 2007, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,21 +22,22 @@
  * @author karasiuk
  *
  */
-public class ValidationResults {
+public final class ValidationResults {
 	
-	private ValidatorMessage[] _messages;
-	private int _error;
-	private int	_warn;
-	private int _info;
+	private final ValidatorMessage[] _messages;
+	private final int 	_error;
+	private final int	_warn;
+	private final int	_info;
 	
 	public ValidationResults(ValidationResult result){
 		if (result == null){
-			_messages = new ValidatorMessage[0];			
+			_messages = new ValidatorMessage[0];
+			_error = 0;
+			_warn = 0;
+			_info = 0;
 		}
 		else {
-			ValidatorMessage[] messages = result.getMessages();
-			_messages = new ValidatorMessage[messages.length];
-			System.arraycopy(messages, 0, _messages, 0, messages.length);
+			_messages = result.getMessagesAsCopy();
 			_error = result.getSeverityError();
 			_warn = result.getSeverityWarning();
 			_info = result.getSeverityInfo();
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationState.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationState.java
index b7a95f7..e0758c7 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationState.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationState.java
@@ -35,7 +35,7 @@
  * @author karasiuk
  *
  */
-public class ValidationState {
+public final class ValidationState {
 	
 	/**
 	 * This is a special id.
@@ -51,7 +51,7 @@
 	public static final String TriggerResource = ValidationPlugin.PLUGIN_ID + ".Trigger"; //$NON-NLS-1$
 
 	// I can't use a ConncurrentHashMap because some of the clients store nulls.
-	private Map<String, Object> _map = new HashMap<String, Object>(50);
+	private final Map<String, Object> _map = new HashMap<String, Object>(50);
 	
 	public ValidationState(){
 	}
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/Validator.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/Validator.java
index 05b6e72..bd08f70 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/Validator.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/Validator.java
@@ -42,7 +42,6 @@
 import org.eclipse.wst.validation.internal.ValManager;
 import org.eclipse.wst.validation.internal.ValMessages;
 import org.eclipse.wst.validation.internal.ValOperation;
-import org.eclipse.wst.validation.internal.ValOperationManager;
 import org.eclipse.wst.validation.internal.ValPrefManagerGlobal;
 import org.eclipse.wst.validation.internal.ValPrefManagerProject;
 import org.eclipse.wst.validation.internal.ValType;
@@ -171,7 +170,7 @@
 	 * @param project the project being built.
 	 * @param monitor the monitor that should be used for reporting progress if the clean takes a long time.
 	 */
-	public void clean(IProject project, IProgressMonitor monitor){
+	public void clean(IProject project, ValOperation operation, IProgressMonitor monitor){
 	}	
 	
 	/**
@@ -907,6 +906,7 @@
 		return super.asIValidator();
 	}
 	
+	@Override
 	public V2 asV2Validator() {
 		return this;
 	}
@@ -916,11 +916,14 @@
 	 * 
 	 * @param project the project that is being cleaned. This can be null which means that the workspace
 	 * is being cleaned (in which case a separate call will be made for each open project).
+	 * 
 	 */
-	public void clean(IProject project, IProgressMonitor monitor) {
-		getDelegatedValidator().clean(project, ValOperationManager.getDefault().getOperation().getState(), monitor);
+	@Override
+	public void clean(IProject project, ValOperation operation, IProgressMonitor monitor) {
+		getDelegatedValidator().clean(project, operation.getState(), monitor);
 	}
 	
+	@Override
 	public Validator copy(boolean includeChangeCounts) {
 		V2 v = null;
 		if (_validatorConfigElement != null)v = new V2(_validatorConfigElement, _project);
@@ -985,6 +988,7 @@
 		return delegated;
 	}
 		
+	@Override
 	public String getId() {
 		return _id;
 	}
@@ -1003,6 +1007,7 @@
 		return groups;
 	}
 	
+	@Override
 	public String getName() {
 		return _name;
 	}
@@ -1026,6 +1031,7 @@
 		return _validator;
 	}
 	
+	@Override
 	public String getValidatorClassname(){
 		return _validatorClassName;
 	}
@@ -1065,6 +1071,7 @@
 	 * 
 	 * @return true if the resource should be validated.
 	 */
+	@Override
 	protected boolean shouldValidate(IResource resource, ContentTypeWrapper contentTypeWrapper) {
 		FilterGroup[] groups = getGroups();
 		IProject project = resource.getProject();
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidatorMessage.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidatorMessage.java
index 70bdd90..b8146dc 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidatorMessage.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidatorMessage.java
@@ -45,7 +45,7 @@
 	public static final String ValidationId = "ValidationId"; //$NON-NLS-1$
 	
 	/** Associate some arbitrary attributes with a message. */
-	private Map<String, Object>	_map = new HashMap<String, Object>(5);
+	private final Map<String, Object>	_map = new HashMap<String, Object>(5);
 	
 	private IResource	_resource;
 	
@@ -73,6 +73,17 @@
 	private ValidatorMessage(){}
 	
 	/**
+	 * Answer a copy of yourself.
+	 */
+	public ValidatorMessage asCopy(){
+		ValidatorMessage msg = new ValidatorMessage();
+		msg._resource = _resource;
+		msg._type = _type;
+		msg._map.putAll(_map);
+		return msg;
+	}
+	
+	/**
 	 * Returns the attribute with the given name. The result is an instance of
 	 * one of the following classes: <code>String</code>, <code>Integer</code>,
 	 * or <code>Boolean</code>. Returns <code>null</code> if the attribute is
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/DebugConstants.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/DebugConstants.java
index f25db09..a466241 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/DebugConstants.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/DebugConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * Copyright (c) 2007, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -45,5 +45,11 @@
 	 * the extension point. All the other validators are ignored.
 	 */
 	String FilterAllExcept = ValidationPlugin.PLUGIN_ID+"/filter/allExcept"; //$NON-NLS-1$
+	
+	/**
+	 * trace/level - The tracing level. If not supplied a default of zero is used. The higher the number the
+	 * more verbose the tracing.
+	 */
+	String TraceLevel = ValidationPlugin.PLUGIN_ID+"/trace/level"; //$NON-NLS-1$
 
 }
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/Misc.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/Misc.java
index bf9beeb..ceafc41 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/Misc.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/Misc.java
@@ -29,7 +29,7 @@
  * @author karasiuk
  *
  */
-public class Misc {
+public final class Misc {
 	
 	public static void close(InputStream in){
 		if (in == null)return;
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/Tracing.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/Tracing.java
index 5a2408a..77e49cb 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/Tracing.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/Tracing.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,6 +14,9 @@
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;
 
@@ -22,16 +25,29 @@
  * @author karasiuk
  *
  */
-public class Tracing {
+public final class Tracing {
 	
-	private static DateFormat 	_df = new SimpleDateFormat("HH:mm:ss.SSSS"); //$NON-NLS-1$
-	private static boolean		_forceLogging;
-	private static Boolean		_traceMatches;
-	private static Boolean		_traceV1;
-	private static String		_extraValDetail;
+	private final static DateFormat _df = new SimpleDateFormat("HH:mm:ss.SSSS"); //$NON-NLS-1$
+	private final static boolean	_isLogging = ValidationPlugin.getPlugin().isDebugging();
+	private final static boolean	_traceMatches = Misc.debugOptionAsBoolean(DebugConstants.TraceMatches);
+	private final static boolean	_traceV1 = Misc.debugOptionAsBoolean(DebugConstants.TraceV1);
+	private final static String		_extraValDetail = Platform.getDebugOption(DebugConstants.ExtraValDetail);
+	private final static int 		_tracingLevel;
 	
-	private static String		_filter;
-	private static boolean		_noFilters;
+	private final static String		_filter = Platform.getDebugOption(DebugConstants.FilterAllExcept);
+	
+	static {
+		String traceLevel = Platform.getDebugOption(DebugConstants.TraceLevel);
+		int level = 0;
+		if (traceLevel != null){
+			try {
+				level = Integer.parseInt(traceLevel);
+			}
+			catch (Exception e){
+			}
+		}
+		_tracingLevel = level;
+	}
 	
 	/**
 	 * Answer true if the filters allow this validator to be enabled. Normally this method will answer true.
@@ -42,12 +58,7 @@
 	 * @return true if the validator should be registered via an extension point.
 	 */
 	public static boolean isEnabled(String validatorId){
-		if (_noFilters)return true;
-		if (_filter == null){
-			_filter = Platform.getDebugOption(DebugConstants.FilterAllExcept);
-			if (_filter == null || _filter.length() == 0)_noFilters = true;
-			return true;
-		}
+		if (_filter == null || _filter.length() == 0)return true;
 		return (_filter.equals(validatorId));		
 	}
 	
@@ -55,29 +66,32 @@
 	 * Are we in logging/debugging mode?
 	 */
 	public static boolean isLogging(){
-		return _forceLogging || ValidationPlugin.getPlugin().isDebugging();
+		return _isLogging;
+	}
+	
+	/**
+	 * Answer true if we are in logging mode, and if the current logging level is greater than or
+	 * equal to level.
+	 * @param level The logging level that we are testing. The higher the level the more verbose
+	 * the tracing.
+	 */
+	public static boolean isLogging(int level){
+		if (_isLogging){
+			return _tracingLevel >= level;
+		}
+		return false;
 	}
 	
 	public static boolean isTraceMatches(){
-		if (_traceMatches == null){
-			_traceMatches = Misc.debugOptionAsBoolean(DebugConstants.TraceMatches);
-		}
 		return _traceMatches;
 	}
 	
 	public static boolean isTraceV1(){
-		if (_traceV1 == null){
-			_traceV1 = Misc.debugOptionAsBoolean(DebugConstants.TraceV1);
-		}
 		return _traceV1;
 	}
 	
 	public static boolean matchesExtraDetail(String validatorId){
-		if (_extraValDetail == null){
-			_extraValDetail = Platform.getDebugOption(DebugConstants.ExtraValDetail);
-			if (_extraValDetail == null)_extraValDetail = ""; //$NON-NLS-1$
-		}
-		if (_extraValDetail.length() == 0)return false;
+		if (_extraValDetail == null)return false;
 		return _extraValDetail.equals(validatorId);
 	}
 
@@ -107,7 +121,7 @@
 
 	public static String timestampIt(String line){
 		Date date = new Date();
-		long thread = Thread.currentThread().getId();
+		String thread = Thread.currentThread().getName();
 		return _df.format(date) + " " + thread + " " + line;  //$NON-NLS-1$//$NON-NLS-2$		
 	}
 
@@ -120,14 +134,75 @@
 	}
 
 	/**
-	 * Force the logging to be turned on. Normally logging is turned on via -debug options. However
-	 * the logging can be forced to be on by setting this to true. (Setting this to false doesn't force
-	 * the logging to be turned off).
+	 * This method doesn't do anything, and will be removed.
 	 * 
-	 * @param forceLogging
+	 * @deprecated
 	 */
 	public static void setForceLogging(boolean forceLogging) {
-		_forceLogging = forceLogging;
+	}
+	
+	/**
+	 * Log up to maxNumber deltas to the log.
+	 * @param delta The deltas to log.
+	 * @param maxNumber The maximum number of deltas to log.
+	 */
+	public static void logResourceDeltas(IResourceDelta delta, int maxNumber){
+		if (!isLogging())return;
+		if (delta == null)Tracing.log("  ResourceDelta: null"); //$NON-NLS-1$
+		else {
+			DeltaLogger logger = new DeltaLogger(maxNumber);
+			try {
+				delta.accept(logger);
+				if (logger.getCount() == 0)Tracing.log("  ResourceDelta: no deltas"); //$NON-NLS-1$
+			}
+			catch (CoreException e){
+				// eat it
+			}
+		}
+	}
+	
+	/**
+	 * A debugging class that prints out some resource delta's.
+	 * @author karasiuk
+	 *
+	 */
+	private final static class DeltaLogger implements IResourceDeltaVisitor {
+		
+		private final int 	_max;
+		private int 		_count;
+		public int getCount() {
+			return _count;
+		}
+
+		private StringBuffer _b = new StringBuffer(200);
+		
+		public DeltaLogger(int max){
+			_max = max;
+		}
+
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			if (_count++ > _max)return false;
+			int kind = delta.getKind();
+			String type = "unknown"; //$NON-NLS-1$
+			switch (kind){
+			case IResourceDelta.ADDED:
+				type = "Added"; //$NON-NLS-1$
+				break;
+			case IResourceDelta.CHANGED:
+				type = "Changed"; //$NON-NLS-1$
+				break;
+			case IResourceDelta.REMOVED:
+				type = "Removed"; //$NON-NLS-1$
+				break;				
+			}
+			_b.append("  ResourceDelta "); //$NON-NLS-1$
+			_b.append(type);
+			_b.append(' ');
+			_b.append(delta.getResource());
+			Tracing.log(_b);
+			return true;
+		}
+		
 	}
 
 }
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValBuilderJob.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValBuilderJob.java
index 5ab8edb..9bff25c 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValBuilderJob.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValBuilderJob.java
@@ -44,27 +44,23 @@
  * <p>
  * This is the main class for supporting build based validation. When triggered it looks at all of the
  * resource changes and determines what needs to be validated. 
+ * </p>
  * @author karasiuk
  *
  */
-public class ValBuilderJob extends WorkspaceJob implements IResourceDeltaVisitor, IResourceVisitor {
+public final class ValBuilderJob extends WorkspaceJob {
 	
 	private static ValBuilderJob _job;
 	private static Queue<ValidationRequest> _work = new LinkedList<ValidationRequest>();
 	
-	/** The monitor to use while running the build. */
-	private IProgressMonitor	_monitor;
-	
-	private SubMonitor			_subMonitor;
-	
-	private ValidationRequest	_request;
-	
+	private final ValOperation _operation = new ValOperation();
+		
 	/** The types of changes we are interested in. */
 	private final static int	InterestedFlags = IResourceDelta.CONTENT | IResourceDelta.ENCODING |
 		IResourceDelta.MOVED_FROM | IResourceDelta.MOVED_TO;
 	
-	public static synchronized void validateProject(IProject project, IResourceDelta delta, int buildKind, ValOperation operation){
-		ValidationRequest request = new ValidationRequest(project, delta, buildKind, operation);
+	public static synchronized void validateProject(IProject project, IResourceDelta delta, int buildKind){
+		ValidationRequest request = new ValidationRequest(project, delta, buildKind);
 		if (_job == null){
 			_job = new ValBuilderJob();
 			_job.add(request);
@@ -116,24 +112,55 @@
 		return super.belongsTo(family);
 	}
 
+	@Override
 	public IStatus runInWorkspace(IProgressMonitor monitor) {
 		Tracing.log("ValBuilderJob-01: Starting"); //$NON-NLS-1$
-		_monitor = monitor;
 		
-		ValidationRequest request = getRequest();
-		while(request != null){
-			_request = request;
-			run();
-			request = getRequest();
+		try {
+			startingValidation(monitor);
+			
+			ValidationRequest request = getRequest();
+			while(request != null){
+				run(request, monitor);
+				request = getRequest();
+			}
 		}
-		_request = null;
+		finally {
+			finishingValidation(monitor);
+		}
 		
 		Tracing.log("ValBuilderJob-02: Finished"); //$NON-NLS-1$
 		return Status.OK_STATUS;
 	}
+
+	private void startingValidation(IProgressMonitor monitor) {
+        IValidatorVisitor startingVisitor = new IValidatorVisitor(){
+
+            public void visit(Validator validator, IProject project, ValType valType, 
+                ValOperation operation, IProgressMonitor monitor) {
+                
+                validator.validationStarting(project, operation.getState(), monitor);                   
+            }               
+        };
+
+        ValManager.getDefault().accept(startingVisitor, null, ValType.Build, getOperation(), monitor);
+	}
 	
-	private void run(){
-		setName(ValMessages.JobName + " " + _request.getProject().getName()); //$NON-NLS-1$
+	private void finishingValidation(IProgressMonitor monitor) {
+		
+		IValidatorVisitor finishedVisitor = new IValidatorVisitor(){
+
+		    public void visit(Validator validator, IProject project, ValType valType,
+		      ValOperation operation, IProgressMonitor monitor) {
+
+		      validator.validationFinishing(project, operation.getState(), monitor);              
+		    }           
+		  };
+		  ValManager.getDefault().accept(finishedVisitor, null, ValType.Build, getOperation(), monitor);
+	}
+
+	private void run(ValidationRequest request, IProgressMonitor monitor){
+		setName(ValMessages.JobName + " " + request.getProject().getName()); //$NON-NLS-1$
 		try {		
 	        IValidatorVisitor startingVisitor = new IValidatorVisitor(){
 
@@ -144,10 +171,10 @@
 	            }               
 	        };
 
-	        ValManager.getDefault().accept(startingVisitor, _request.getProject(), ValType.Build, _request.getOperation(), _monitor);
+	        ValManager.getDefault().accept(startingVisitor, request.getProject(), ValType.Build, getOperation(), monitor);
 		  
-			if (_request.getDelta() == null)fullBuild();
-			else deltaBuild();
+			if (request.getDelta() == null)fullBuild(request, monitor);
+			else deltaBuild(request, monitor);
 
 			
 		}
@@ -169,77 +196,33 @@
 		      validator.validationFinishing(project, operation.getState(), monitor);              
 		    }           
 		  };
-          ValManager.getDefault().accept(finishedVisitor, _request.getProject(), ValType.Build, _request.getOperation(), _monitor);
+          ValManager.getDefault().accept(finishedVisitor, request.getProject(), ValType.Build, getOperation(), monitor);
 		}
 		
 	}
 
-	private void deltaBuild() throws CoreException {
+	private void deltaBuild(ValidationRequest request, IProgressMonitor monitor) throws CoreException {
 		ResourceCounter counter = new ResourceCounter();
-		_request.getDelta().accept(counter);
-		_subMonitor = SubMonitor.convert(_monitor, counter.getCount());
-		_request.getDelta().accept(this);		
+		request.getDelta().accept(counter);
+		SubMonitor subMonitor = SubMonitor.convert(monitor, counter.getCount());
+		Visitor vistitor = new Visitor(request, subMonitor, monitor, getOperation());
+		request.getDelta().accept(vistitor);		
 	}
 
-	private void fullBuild() throws CoreException {
+	private void fullBuild(ValidationRequest request, IProgressMonitor monitor) throws CoreException {
 		ResourceCounter counter = new ResourceCounter();
-		_request.getProject().accept(counter, 0);
-		_subMonitor = SubMonitor.convert(_monitor, counter.getCount());
-		_request.getProject().accept(this);
+		request.getProject().accept(counter, 0);
+		SubMonitor subMonitor = SubMonitor.convert(monitor, counter.getCount());
+		Visitor vistitor = new Visitor(request, subMonitor, monitor, getOperation());
+		request.getProject().accept(vistitor);
 		
 	}
-
-	@SuppressWarnings("deprecation")
-	public boolean visit(IResourceDelta delta) throws CoreException {
-		IResource resource = delta.getResource();
-		if (DisabledResourceManager.getDefault().isDisabled(resource)){
-			MarkerManager.getDefault().deleteMarkers(resource, _request.getOperation().getStarted(), IResource.DEPTH_INFINITE);
-			return false;
-		}
-		int kind = delta.getKind();
-		boolean isChanged = (kind & IResourceDelta.CHANGED) != 0;
-		if (isChanged &&  (delta.getFlags() & InterestedFlags) == 0)return true;
-		
-		if ((kind & (IResourceDelta.ADDED | IResourceDelta.CHANGED)) != 0){
-			ValManager.getDefault().validate(_request.getProject(), resource, delta.getKind(), ValType.Build, 
-				_request.getBuildKind(), _request.getOperation(), _subMonitor.newChild(1));
-		}
-				
-		IDependencyIndex index = ValidationFramework.getDefault().getDependencyIndex();
-		if (index.isDependedOn(resource)){
-			MarkerManager mm = MarkerManager.getDefault();
-			for (DependentResource dr : index.get(resource)){
-				Validator val = dr.getValidator();
-				if (Friend.shouldValidate(val, dr.getResource(), ValType.Build, new ContentTypeWrapper())){
-					_request.getOperation().getState().put(ValidationState.TriggerResource, resource);
-					ValidationEvent event = new ValidationEvent(dr.getResource(), IResourceDelta.NO_CHANGE, delta);
-					if (val.shouldClearMarkers(event))mm.clearMarker(dr.getResource(), val); 
-					ValManager.getDefault().validate(val, _request.getOperation(), dr.getResource(), 
-						IResourceDelta.NO_CHANGE, _monitor, event);
-				}
-			}
-		}
-				
-		return true;
-	}
-
-	public boolean visit(IResource resource) throws CoreException {
-		try {
-			if (DisabledResourceManager.getDefault().isDisabled(resource)){
-				MarkerManager.getDefault().deleteMarkers(resource, _request.getOperation().getStarted(), IResource.DEPTH_INFINITE);
-				return false;
-			}
-			ValManager.getDefault().validate(_request.getProject(), resource, IResourceDelta.NO_CHANGE, ValType.Build, 
-				_request.getBuildKind(), _request.getOperation(), _subMonitor.newChild(1));
-		}
-		catch (ResourceUnavailableError e){
-			if (Tracing.isLogging())Tracing.log("ValBuilderJob-02: " + e.toString()); //$NON-NLS-1$
-			return false;
-		}
-		return true;
-	}
 	
-	static class ResourceCounter implements IResourceProxyVisitor, IResourceDeltaVisitor {
+	private ValOperation getOperation(){
+		return _operation;
+	}
+
+	static final class ResourceCounter implements IResourceProxyVisitor, IResourceDeltaVisitor {
 		
 		private int _count;
 
@@ -258,27 +241,24 @@
 		}		
 	}
 	
-	static class ValidationRequest {
+	static final class ValidationRequest {
 		/** The project that is being built. */
-		private IProject 			_project;
+		private final IProject 			_project;
 		
 		/** The resource delta that triggered the build, it will be null for a full build. */
-		private IResourceDelta		_delta;
-		
-		private ValOperation		_operation;
+		private final IResourceDelta	_delta;
 		
 		/** 
 		 * The kind of build.
 		 * 
 		 *  @see org.eclipse.core.resources.IncrementalProjectBuilder
 		 */
-		private int					_buildKind;
+		private final int					_buildKind;
 		
-		public ValidationRequest(IProject project, IResourceDelta delta, int buildKind, ValOperation operation){
+		public ValidationRequest(IProject project, IResourceDelta delta, int buildKind){
 			_project = project;
 			_delta = delta;
 			_buildKind = buildKind;
-			_operation = operation;
 		}
 
 		public IProject getProject() {
@@ -289,13 +269,76 @@
 			return _delta;
 		}
 
-		public ValOperation getOperation() {
-			return _operation;
-		}
-
 		public int getBuildKind() {
 			return _buildKind;
 		}
 	}
+	
+	private final static class Visitor implements IResourceDeltaVisitor, IResourceVisitor{
+		
+		private final ValidationRequest 	_request;
+		private final SubMonitor 			_subMonitor;
+		private final IProgressMonitor 		_monitor;
+		private final ValOperation			_operation;
+		
+		public Visitor(ValidationRequest request, SubMonitor subMonitor, IProgressMonitor monitor, ValOperation operation){
+			_request = request;
+			_subMonitor = subMonitor;
+			_monitor = monitor;
+			_operation = operation;
+		}
+		
+		public boolean visit(IResource resource) throws CoreException {
+			try {
+				if (DisabledResourceManager.getDefault().isDisabled(resource)){
+					MarkerManager.getDefault().deleteMarkers(resource, _operation.getStarted(), IResource.DEPTH_INFINITE);
+					return false;
+				}
+				ValManager.getDefault().validate(_request.getProject(), resource, IResourceDelta.NO_CHANGE, ValType.Build, 
+					_request.getBuildKind(), _operation, _subMonitor.newChild(1));
+			}
+			catch (ResourceUnavailableError e){
+				if (Tracing.isLogging())Tracing.log("ValBuilderJob-02: " + e.toString()); //$NON-NLS-1$
+				return false;
+			}
+			return true;
+		}
+		
+		@SuppressWarnings("deprecation")
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			IResource resource = delta.getResource();
+			if (DisabledResourceManager.getDefault().isDisabled(resource)){
+				MarkerManager.getDefault().deleteMarkers(resource, _operation.getStarted(), IResource.DEPTH_INFINITE);
+				return false;
+			}
+			int kind = delta.getKind();
+			boolean isChanged = (kind & IResourceDelta.CHANGED) != 0;
+			if (isChanged &&  (delta.getFlags() & InterestedFlags) == 0)return true;
+			
+			if ((kind & (IResourceDelta.ADDED | IResourceDelta.CHANGED)) != 0){
+				ValManager.getDefault().validate(_request.getProject(), resource, delta.getKind(), ValType.Build, 
+					_request.getBuildKind(), _operation, _subMonitor.newChild(1));
+			}
+					
+			IDependencyIndex index = ValidationFramework.getDefault().getDependencyIndex();
+			if (index.isDependedOn(resource)){
+				MarkerManager mm = MarkerManager.getDefault();
+				for (DependentResource dr : index.get(resource)){
+					Validator val = dr.getValidator();
+					if (Friend.shouldValidate(val, dr.getResource(), ValType.Build, new ContentTypeWrapper())){
+						_operation.getState().put(ValidationState.TriggerResource, resource);
+						ValidationEvent event = new ValidationEvent(dr.getResource(), IResourceDelta.NO_CHANGE, delta);
+						if (val.shouldClearMarkers(event))mm.clearMarker(dr.getResource(), val); 
+						ValManager.getDefault().validate(val, _operation, dr.getResource(), 
+							IResourceDelta.NO_CHANGE, _monitor, event);
+					}
+				}
+			}
+					
+			return true;
+		}
+
+		
+	}
 
 }
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValManager.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValManager.java
index 3998019..3b2d041 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValManager.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValManager.java
@@ -934,7 +934,7 @@
 
 			public void visit(Validator validator, IProject project, ValType valType,
 				ValOperation operation, IProgressMonitor monitor) {
-				validator.clean(project, monitor);					
+				validator.clean(project, operation, monitor);					
 			}
 			
 		};
@@ -952,7 +952,7 @@
 
 			public void visit(Validator validator, IProject project, ValType valType,
 				ValOperation operation, IProgressMonitor monitor) {
-				validator.clean(project, monitor);					
+				validator.clean(project, operation, monitor);					
 			}
 			
 		};
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperation.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperation.java
index a5de936..44c78ec 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperation.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperation.java
@@ -90,6 +90,10 @@
 		}
 	}
 		
+	/**
+	 * Answer a copy of the ValidationResult.
+	 * @return
+	 */
 	public ValidationResults getResults(){
 		return new ValidationResults(_result);
 	}
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationJob.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationJob.java
index 9414c02..48d89ed 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationJob.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationJob.java
@@ -18,6 +18,7 @@
 import org.eclipse.wst.validation.ValidationFramework;
 import org.eclipse.wst.validation.Validator;
 import org.eclipse.wst.validation.internal.model.IValidatorVisitor;
+import org.eclipse.wst.validation.internal.operations.ValidationBuilder;
 
 /**
  * This is used to signal when the entire validation operation is complete. This needs to be done in a job
@@ -25,14 +26,23 @@
  * @author karasiuk
  *
  */
-public class ValOperationJob extends Job {
+public final class ValOperationJob extends Job {
 	
-	private ValOperation _operation;
+	private final ValOperation _operation;
 	
 	public ValOperationJob(ValOperation operation){
 		super(ValMessages.JobNameMonitor);
 		_operation = operation;
 	}
+	
+	@Override
+	public boolean belongsTo(Object family) {
+		if (family == ValidationBuilder.FamilyValidationFinishedJob){
+			return true;
+		}
+
+		return super.belongsTo(family);
+	}
 
 	@Override
 	protected IStatus run(IProgressMonitor monitor) {
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationManager.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationManager.java
deleted file mode 100644
index 63d78ea..0000000
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationManager.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 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.validation.internal;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.eclipse.core.resources.IProject;
-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.IWorkspace;
-import org.eclipse.core.resources.IncrementalProjectBuilder;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.wst.validation.Validator;
-import org.eclipse.wst.validation.internal.model.IValidatorVisitor;
-
-/**
- * Keep track of a validation operation when it is triggered as part of a build.
- * @author karasiuk
- *
- */
-public class ValOperationManager implements IResourceChangeListener {
-	
-	/*
-	 * I tried various tests to see what sort of change events I would get. This is what I 
-	 * observed using Eclipse 3.4:
-	 * 
-	 * Auto Build On
-	 * 
-	 *   Clean All
-	 *     - workspace, clean, pre
-	 *     - workspace, clean post
-	 *     - workspace, auto, post
-	 *     
-	 *   Clean Some
-	 *     - project1, clean, pre
-	 *     - project1, clean, post
-	 *     - project2, clean, pre
-	 *     - project2, clean, post
-	 *     - workspace, Auto, post
-	 *     
-	 *   Build Working Set - NA
-	 *   Build Project - NA
-	 *   Build All - NA
-	 *   
-	 *   Ctrl-S
-	 *     - workspace, auto, pre
-	 *     - workspace, auto, post
-	 *     
-	 * Auto build Off
-	 * 
-	 *   Clean All
-	 *     - same as (auto build on), but no workspace,auto,post event
-	 *     
-	 *   Clean Some 
-	 *     - same as (auto build on), but no workspace,auto,post event
-	 *     
-	 *   Build Working Set
-	 *     - project1, incremental, pre
-	 *     - project1, incremental, post
-	 *     - project2, incremental, pre
-	 *     - project2, incremental, post
-	 *     
-	 *   Build Project
-	 *     - same as above
-	 *     
-	 *   Build All
-	 *     - workspace, incremental, pre
-	 *     - workspace, incremental, post
-	 *     
-	 *   Ctrl-S - NA
-	 *   
-	 * For the case where a subset of the projects are built there is no way to guess whether they are part of the
-	 * same operation or not. Eclipse threats them as independent events, and so will the validation framework.
-	 * 
-	 * So for example, if the user selected two projects (p1 and p2) and built them, the framework would call the
-	 * validators like this:
-	 * 
-	 * validation starting on null
-	 * validation starting on P1
-	 *  - individual events per resource
-	 * validation finished on P1
-	 * validation finished on null 
-	 * 
-	 * validation starting on null
-	 * validation starting on P2
-	 *  - individual events per resource
-	 * validation finished on P2
-	 * validation finished on null 
-	 */
-	
-	/**
-	 * This operation is in affect for a build cycle. At the end of the build it is reinitialized.
-	 */
-	private ValOperation 	_operation;
-	
-	
-	/**
-	 * In the very common case of doing a clean all (with auto build turned on), Eclipse signals two 
-	 * workspace, auto build, post events. One at the end of the clean and one at the end of the
-	 * real build.
-	 * 
-	 * If we are doing a clean all, with auto build turned on, we increment this by one, 
-	 * so that we know to throw away the first workspace, auto build, post event.
-	 */
-	private AtomicInteger _discardAutoPost = new AtomicInteger();
-
-	public static ValOperationManager getDefault(){
-		return Singleton.valOperationManager;
-	}
-	
-	private ValOperationManager(){}
-				
-	public void resourceChanged(IResourceChangeEvent event) {
-		int type = event.getType();
-		int kind = event.getBuildKind();
-		
-		if (kind == IncrementalProjectBuilder.CLEAN_BUILD && ((type & IResourceChangeEvent.PRE_BUILD) != 0)){
-			processClean(event);
-		}
-		
-		if (isBuildStarting(event)){
-			synchronized(this){
-				_operation = new ValOperation(true);
-			}
-			IValidatorVisitor visitor = new IValidatorVisitor(){
-
-				public void visit(Validator validator, IProject project, ValType valType, 
-					ValOperation operation, IProgressMonitor monitor) {
-					
-					validator.validationStarting(project, operation.getState(), monitor);					
-				}				
-			};
-			ValManager.getDefault().accept(visitor, null, ValType.Build, _operation, new NullProgressMonitor());
-			
-		}
-		
-		if (isBuildFinished(event)){
-			ValOperationJob finished = new ValOperationJob(getOperation());
-			finished.schedule();
-			synchronized(this){
-				_operation = null;
-			}
-		}
-		
-		
-		if (Tracing.isLogging()){
-			String kindName = null;
-			if (kind == IncrementalProjectBuilder.AUTO_BUILD)kindName = "Auto"; //$NON-NLS-1$
-			else if (kind == IncrementalProjectBuilder.CLEAN_BUILD)kindName = "Clean"; //$NON-NLS-1$
-			else if (kind == IncrementalProjectBuilder.FULL_BUILD)kindName = "Full"; //$NON-NLS-1$
-			else if (kind == IncrementalProjectBuilder.INCREMENTAL_BUILD)kindName = "Incremental"; //$NON-NLS-1$
-			else kindName = String.valueOf(kind);
-			
-			StringBuffer b = new StringBuffer(100);
-			
-			String sourceName = "unknown"; //$NON-NLS-1$
-			if (event.getSource() instanceof IResource) {
-				IResource res = (IResource) event.getSource();
-				sourceName = res.getName();
-			}
-			else if (event.getSource() instanceof IWorkspace) {
-				sourceName = "Workspace";			 //$NON-NLS-1$
-			}
-			b.append("ValOperationManager-01: A resource has changed, source="+sourceName+", kind="+kindName+", event type=("+type); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-			if ((type & IResourceChangeEvent.POST_BUILD) != 0)b.append(", post build"); //$NON-NLS-1$
-			if ((type & IResourceChangeEvent.PRE_BUILD) != 0){
-				b.append(", pre build"); //$NON-NLS-1$
-			}
-			b.append(')');
-			IResourceDelta rd = event.getDelta();
-			if (rd == null)b.append(", there was no resource delta"); //$NON-NLS-1$
-			
-			Tracing.log(b);
-		}
-		
-	}
-	
-	/**
-	 * Determine if we are starting a new build cycle.
-	 * @param event
-	 * @return
-	 */
-	private boolean isBuildStarting(IResourceChangeEvent event) {
-		int type = event.getType();
-		int kind = event.getBuildKind();
-		boolean isWorkspace = event.getSource() instanceof IWorkspace;
-		boolean preBuild = (type & IResourceChangeEvent.PRE_BUILD) != 0;
-		
-		if (ResourcesPlugin.getWorkspace().isAutoBuilding()){
-			if (isWorkspace && preBuild && kind == IncrementalProjectBuilder.CLEAN_BUILD){
-				_discardAutoPost.set(1);
-				return true;
-			}
-			
-			if (isWorkspace && preBuild && kind == IncrementalProjectBuilder.AUTO_BUILD)return true;
-		}
-		else {
-			if (isWorkspace && preBuild && kind == IncrementalProjectBuilder.INCREMENTAL_BUILD)return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Determine if we are at the end of a build cycle. This will give callers the ability to
-	 * clear caches etc.
-	 *  
-	 * @param event
-	 * @return return true if we are just finishing a build.
-	 */
-	private boolean isBuildFinished(IResourceChangeEvent event) {
-		synchronized(this){
-			if (_operation == null)return false;
-		}
-		
-		int type = event.getType();
-		int kind = event.getBuildKind();
-		boolean isWorkspace = event.getSource() instanceof IWorkspace;
-		boolean postBuild = (type & IResourceChangeEvent.POST_BUILD) != 0;
-
-		
-		if (ResourcesPlugin.getWorkspace().isAutoBuilding()){
-			if (isWorkspace && postBuild && kind == IncrementalProjectBuilder.AUTO_BUILD){
-				if (!_discardAutoPost.compareAndSet(1, 0))return true;
-			}
-		}
-		else {
-			if (isWorkspace && postBuild && kind == IncrementalProjectBuilder.INCREMENTAL_BUILD)return true;
-		}
-		
-		return false;
-	}
-	
-	private void processClean(IResourceChangeEvent event){
-		// Originally I was using this to monitor IProject build requests as well, but that is not not needed
-		// since these will be handled by the IncrementalProjectBuilder.clean() method.
-		IProgressMonitor monitor = new NullProgressMonitor();
-		Object source = event.getSource();
-		if (source instanceof IWorkspace) {
-			ValManager.getDefault().clean(null, getOperation(), monitor);
-		}
-		
-	}
-
-	/**
-	 * Answer the current validation operation. If we are not in a multiple project validation
-	 * we will return a new one. 
-	 */
-	public synchronized ValOperation getOperation() {
-		/*
-		 * If we don't have a current operation, we create a new one. The only time we save
-		 * the operation is when we are sure that we are in a multi project validation.
-		 */
-		if (_operation == null)return new ValOperation();
-		return _operation;
-	}
-	
-	/**
-	 * Store the singleton for the ValOperationManager. This approach is used to avoid having to synchronize the
-	 * ValOperationManager.getDefault() method.
-	 * 
-	 * @author karasiuk
-	 *
-	 */
-	private static class Singleton {
-		static ValOperationManager valOperationManager = new ValOperationManager();
-	}
-
-
-}
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationResultSummary.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationResultSummary.java
index 2c124bd..d8edf9b 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationResultSummary.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationResultSummary.java
@@ -1,10 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
 package org.eclipse.wst.validation.internal;
 
-public class ValidationResultSummary {
+/**
+ * An immutable object that holds a summari of the validation.
+ * @author karasiuk
+ *
+ */
+public final class ValidationResultSummary {
 	
-	private int _error;
-	private int _warning;
-	private int	_info;
+	private final int 	_error;
+	private final int 	_warning;
+	private final int	_info;
 	
 	public ValidationResultSummary(int error, int warning, int info){
 		_error = error;
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/package.html b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/package.html
index 980067a..62a674b 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/package.html
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/package.html
@@ -28,7 +28,7 @@
 product.
 <p>In particular when the validate method returns, a
 <a href="ValidationResult.html">ValidationResult</a> must be returned, inside of 
-this result, all your dependencies need to be specified with the&nbsp;
+this result, all your dependencies need to be specified with the
 <a href="ValidationResult.html#setDependsOn(org.eclipse.core.resources.IResource[])">
 setDependsOn</a> method.<p>In addition to keeping the dependency information 
 up-to-date through the normal course of validation, direct access is also 
@@ -36,5 +36,16 @@
 <a href="ValidationFramework.html#getDependencyIndex()">getDependencyIndex</a> 
 method. The <a href="IDependencyIndex.html">IDependencyIndex</a> allows you to 
 directly manipulate the dependency information for a validator.
+<h3>Entry Points into the Validation Framework</h3>
+<p>Here are some of the points where the platform calls into the framework:</p>
+<ul>
+<li><b>Builder</b> - ValidationBuilder</li>
+<li><b>IFacetedProjectListener</b> - ValManager</li>
+<li><b>IJobChangeListener</b> - ValidationOperation, ValidationOperation.ValidationLauncherJob</li>
+<li><b>IProjectChangeListener</b> - ValManager</li>
+<li><b>IPropertyChangeListener</b> - ValidationConfiguration, DisabledResourceManager</li>
+<li><b>IResourceChangeListener</b> - ValOperationManager, EventManger</li>
+<li><b>IValChangedListener</b> - ValManager, DisabledValidatorManager</li>
+</ul>
 </body>
 </html>