/*******************************************************************************
 * Copyright (c) 2001, 2004 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.operations;

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jem.util.logger.LogEntry;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.wst.validation.internal.ResourceConstants;
import org.eclipse.wst.validation.internal.ResourceHandler;
import org.eclipse.wst.validation.internal.TaskListUtility;
import org.eclipse.wst.validation.internal.ValidationRegistryReader;
import org.eclipse.wst.validation.internal.ValidatorMetaData;
import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
import org.eclipse.wst.validation.internal.provisional.core.IValidator;
import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;

/**
 * IValidator instances will interact with an instance of this class, but should never cast that
 * IReporter instance to WorkbenchReporter. The WorkbenchReporter class will be moved in Milestone
 * 4.
 * 
 * This class handles interaction between the user and the IValidator in the eclipse workbench
 * environment.
 * 
 * This class must not be called outside of an IWorkspaceRunnable or IRunnableWithProgress. Many
 * resource deltas can be generated by the methods in this class.
 * 
 * Only the validation framework may instantiate or alter instances of this class.
 */

public final class WorkbenchReporter implements IReporter {
	public static final String DEFAULT_LOCATION = ""; //$NON-NLS-1$
	public static final int NO_MESSAGE_LIMIT = -1;

	private IProject _project;
	private IProgressMonitor _monitor;

	public static void addMessage(IResource resource, Class messageOwner, IMessage message) {
		addMessage(resource, messageOwner, null, message); // null ClassLoader = use the default
		// (clazz.getClassLoader());
	}
	
	public static void addMessage(IResource resource, Class messageOwner, ClassLoader cl, IMessage message) {
		addMessage(resource, messageOwner, cl, message, null, ""); //$NON-NLS-1$
	}
	
	public static void addMessage(IResource resource, Class clazz, IMessage message, String targetObjectName, String location) {
		addMessage(resource, clazz, null, message, targetObjectName, location); // null = use the
		// default
		// ClassLoader
		// (class.getClassLoader())
	}
	
	public static void addMessage(IResource resource, Class clazz, IMessage message, String targetObjectName, String location,String markerId) {
		addMessage(resource, clazz, null, message, targetObjectName, location,markerId); // null = use the
		// default
		// ClassLoader
		// (class.getClassLoader())
	}
	
	

	public static void addMessage(IResource resource, Class clazz, ClassLoader cl, IMessage message, String targetObjectName, String location) {
		if ((clazz == null) || (message == null) || (resource == null)) {
			return;
		}

		if (cl == null) {
			cl = clazz.getClassLoader();
		}

		addMessage(resource, getUniqueId(clazz), cl, message, targetObjectName, location);
	}
	
	public static void addMessage(IResource resource, Class clazz, ClassLoader cl, IMessage message, String targetObjectName, String location, String markerId) {
		if ((clazz == null) || (message == null) || (resource == null)) {
			return;
		}

		if (cl == null) {
			cl = clazz.getClassLoader();
		}

		addMessage(resource, getUniqueId(clazz), cl, message, targetObjectName, location, markerId);
	}

	public static void addMessage(IResource resource, String messageOwnerId, ClassLoader cl, IMessage message) {
		addMessage(resource, messageOwnerId, cl, message, null, ""); //$NON-NLS-1$
	}

	public static void addMessage(IResource resource, String messageOwnerId, ClassLoader cl, IMessage message, String targetObjectName, String location) {
		int severity = message.getSeverity();
		try {
			TaskListUtility.addTask(messageOwnerId, resource, location, message.getId(), message.getText(cl), severity,targetObjectName, message.getGroupName(), message.getOffset(), message.getLength());
		} catch (CoreException exc) {
			// Couldn't add the task to the task list for some reason...
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter.addMessage(Class,, IResource, IMessage, String, String"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
	}
	
	public static void addMessage(IResource resource, String messageOwnerId, ClassLoader cl, IMessage message, String targetObjectName, String location, String markerId) {
		int severity = message.getSeverity();
		try {
			TaskListUtility.addTask(messageOwnerId, resource, location, message.getId(), message.getText(cl), severity,markerId,targetObjectName, message.getGroupName(), message.getOffset(), message.getLength());
		} catch (CoreException exc) {
			// Couldn't add the task to the task list for some reason...
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter.addMessage(Class,, IResource, IMessage, String, String"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
	}
	
	

	public static void removeAllMessages(IResource resource, IValidator validator) {
		if (resource == null) {
			return;
		}

		ValidatorMetaData vmd = ValidationRegistryReader.getReader().getValidatorMetaData(validator);
		if (vmd == null) {
			// log
			return;
		}

		String[] validatorNames = vmd.getValidatorNames();
		try {
			TaskListUtility.removeAllTasks(resource, validatorNames);
		} catch (CoreException exc) {
			// Couldn't remove the task from the task list for some reason...
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter.removeAllMessages(String[], IResource, String)"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
	}

	/**
	 * @deprecated Will be removed in Milestone 3. Should not be called outside of the validation
	 *             framework.
	 */
	public static void removeAllMessages(IResource resource, IValidator validator, Object object) {
		if (resource == null) {
			return;
		}

		ValidatorMetaData vmd = ValidationRegistryReader.getReader().getValidatorMetaData(validator);
		if (vmd == null) {
			// log
			return;
		}

		String[] validatorNames = vmd.getValidatorNames();
		try {
			//String targetObjectName = getTargetObjectName(vmd.getHelper(resource.getProject()), object);
			String targetObjectName = getTargetObjectName( getHelper( resource.getProject(), validator), object);			
			removeAllMessages(resource, validatorNames, targetObjectName);
		} catch (InstantiationException exc) {
			// Remove the vmd from the reader's list
			ValidationRegistryReader.getReader().disableValidator(vmd);

			// Log the reason for the disabled validator
			final Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter::removeAllMessages(IResource, IValidator, Object)"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
	}

	public static void removeAllMessages(IResource resource, String[] validatorNames, String targetObjectName) {
		try {
			TaskListUtility.removeAllTasks(resource, validatorNames, targetObjectName);
		} catch (CoreException exc) {
			// Couldn't remove the task from the task list for some reason...
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter.removeAllMessages(String[], IResource, String)"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
	}

	public static void removeMessageSubset(IResource resource, Class messageOwner, String groupName) {
		// Since the addMessage(Class, IMessage) is defaulted to the IProject,
		// remove the message subsets from the IProject
		removeMessageSubset(resource, new String[]{getUniqueId(messageOwner)}, null, groupName);
	}

	public static void removeMessageSubset(IResource resource, String messageOwnerId, String groupName) {
		// Since the addMessage(Class, IMessage) is defaulted to the IProject,
		// remove the message subsets from the IProject
		removeMessageSubset(resource, new String[]{messageOwnerId}, null, groupName);
	}

	public static void removeMessageSubset(IResource resource, String[] ownerId, String targetObjectName, String groupName) {
		try {
			TaskListUtility.removeTaskSubset(resource, ownerId, targetObjectName, groupName);
		} catch (CoreException exc) {
			// Couldn't remove the task to the task list for some reason...
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter.removeMessageSubset(String[], IResource, String, String)"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
	}

	/**
	 * Given a Class instance, return the id that uniquely identifies this instance. (Used as the
	 * value for the message owner.)
	 */
	public static String getUniqueId(Class clazz) {
		if (clazz == null) {
			return ""; //$NON-NLS-1$
		}

		// It is safe to load this String into the constants space because
		// the Class name will not change during WSAD's session.
		return clazz.getName().intern();
	}

	public static String getUniqueId(IValidator validator) {
		if (validator == null) {
			return ""; //$NON-NLS-1$
		}
		return getUniqueId(validator.getClass());
	}

	public static Logger getMsgLogger(IValidator validator) {
		ValidatorMetaData vmd = ValidationRegistryReader.getReader().getValidatorMetaData(validator);
		if (vmd == null) {
			return ValidationPlugin.getPlugin().getMsgLogger();
		}

		return vmd.getMsgLogger();
	}

	public static String getLocation(IWorkbenchContext helper, IMessage message) {
		if (message == null) {
			return getLocationText(helper, null);
		}
		int lineNo = message.getLineNumber();
		if (lineNo == IMessage.LINENO_UNSET) {
			return getLocationText(helper, message.getTargetObject());
		}
		return String.valueOf(lineNo);
	}

	public static String getLocationText(IWorkbenchContext helper, Object targetObject) {
		String location = null;
		try {
			location = helper.getLocation(targetObject);
		} catch (Exception exc) {
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter.getLocationText(Object)"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
		if ((location == null) || (location.trim().equals(""))) { //$NON-NLS-1$
			location = DEFAULT_LOCATION;
		}
		return location;
	}

	// TODO This method was made protected for the SaberReporter. Make this method private again
	// once the framework supports IMarker.PRIORITY.
	protected static String getTargetObjectName(IWorkbenchContext helper, IMessage message) {
		if (message == null) {
			return getTargetObjectName(helper, null);
		}
		return getTargetObjectName(helper, message.getTargetObject());
	}

	private static String getTargetObjectName(IWorkbenchContext helper, Object targetObject) {
		String targetObjectName = null;
		try {
			targetObjectName = helper.getTargetObjectName(targetObject);
		} catch (Exception exc) {
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter.getTargetObjectName(Object)"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}
		}
		return targetObjectName;
	}

	// TODO This method was made "protected" for the SaberReporter. Do not call this method! This
	// method will be made private once support for marker PRIORITY attributes is in the framework.
	protected static ValidatorMetaData getVMD(IValidator validator) throws IllegalArgumentException {
		ValidatorMetaData vmd = ValidationRegistryReader.getReader().getValidatorMetaData(validator);
		if (vmd == null) {
			throw new IllegalArgumentException(); // already logged in the ValidationRegistryReader
		}
		return vmd;
	}

	/**
	 * @deprecated. The IValidationContext will be ignored.
	 */
	public WorkbenchReporter(IWorkbenchContext helper, IProgressMonitor monitor, IProject project) {
		this(project, monitor);
	}

	/**
	 * An IReporter instance must exist for each Runnable in order for the validator to report
	 * status messages. IProject and IProgressMonitor must not be null.
	 */
	public WorkbenchReporter(IProject project, IProgressMonitor monitor) {
		super();
		_project = project;
		_monitor = monitor;
	}

	// TODO This method was made protected for the SaberReporter. Make it private again once the
	// framework support IMarker.PRIORITY.
	protected IWorkbenchContext getHelper(IValidator validator) throws InstantiationException, IllegalArgumentException {
		ValidatorMetaData vmd = getVMD(validator);
		IWorkbenchContext helper = vmd.getHelper( getProject(), validator );
		return helper;
	}
	
	protected static IWorkbenchContext getHelper(IProject project, IValidator validator) throws InstantiationException, IllegalArgumentException {
		ValidatorMetaData vmd = getVMD(validator);
		IWorkbenchContext helper = vmd.getHelper( project, validator );
		return helper;
	}
	
	public IProject getProject() {
		return _project;
	}

	public IProgressMonitor getProgressMonitor() {
		return _monitor;
	}

	/**
	 * This method will never return null.
	 */
	private IResource getDefaultResource() {
		IResource prj = getProject();
		if (prj != null) {
			return prj;
		}
		// return the workspace root
		return ResourcesPlugin.getWorkspace().getRoot();
	}

	/**
	 * When an IMessage is created, the user has the option of creating it with a target object.
	 * That target object is used to identify which object has the problem identified by the
	 * IMessage. This method, given the target object, returns the IResource which represents that
	 * object in the workbench.
	 */
	public IResource getMessageResource(IValidator validator, Object object) {
		if (validator == null) {
			return null;
		}

		IResource resource = null;
		if (object != null) {
			if (object instanceof IResource) {
				resource = (IResource) object;
			} else if (object instanceof WorkbenchFileDelta) {
				// resource may be null if the WorkbenchFileDelta was constructed from an Object
				// instead of an IResource
				resource = ((WorkbenchFileDelta) object).getResource();
			}

			if (resource == null) {
				try {
					IWorkbenchContext helper = getHelper(validator);
					resource = helper.getResource(object);
				} catch (InstantiationException exc) {
					try {
						// Unlikely that an exception will be thrown, because this method is
						// invoked by the validator, and if the validator is invoked, it's likely
						// that the helper has been loaded too.
						ValidatorMetaData vmd = getVMD(validator);

						// Remove the vmd from the reader's list
						ValidationRegistryReader.getReader().disableValidator(vmd);

						// Log the reason for the disabled validator
						Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
						if (logger.isLoggingLevel(Level.SEVERE)) {
							LogEntry entry = ValidationPlugin.getLogEntry();
							entry.setSourceID("WorkbenchReporter::getMessageResource(IValidator, Object)"); //$NON-NLS-1$
							entry.setTargetException(exc);
							logger.write(Level.SEVERE, entry);
						}
					} catch (IllegalArgumentException exc2) {
						// Even the IValidator is invalid. Unfortunately, can't disable the
						// validator because it can't be found by the registry reader.
						// Log the reason for the disabled validator
						Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
						if (logger.isLoggingLevel(Level.SEVERE)) {
							LogEntry entry = ValidationPlugin.getLogEntry();
							entry.setSourceID("WorkbenchReporter::getMessageResource(IValidator, Object)"); //$NON-NLS-1$
							entry.setTargetException(exc2);
							logger.write(Level.SEVERE, entry);
						}
					}
				} catch (IllegalArgumentException exc) {
					// Even the IValidator is invalid. Unfortunately, can't disable the
					// validator because it can't be found by the registry reader.
					// Log the reason for the disabled validator
					Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
					if (logger.isLoggingLevel(Level.SEVERE)) {
						LogEntry entry = ValidationPlugin.getLogEntry();
						entry.setSourceID("WorkbenchReporter::getMessageResource(IValidator, Object)"); //$NON-NLS-1$
						entry.setTargetException(exc);
						logger.write(Level.SEVERE, entry);
					}
				} catch (Exception exc) {
					Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
					if (logger.isLoggingLevel(Level.SEVERE)) {
						LogEntry entry = ValidationPlugin.getLogEntry();
						entry.setSourceID("WorkbenchReporter.getMessageResource(IValidator, Object)"); //$NON-NLS-1$
						entry.setTargetException(exc);
						logger.write(Level.SEVERE, entry);
					}
				}
			}
		}

		if (resource == null) {
			resource = getDefaultResource();
		}

		if (!resource.exists()) {
			resource = getDefaultResource();
		}

		return resource;
	}

	/**
	 * Show a message to the user indicating which subtask is currently being processed. <br>
	 * <br>
	 * <code>message</code> may not be null or the empty string (""). <br>
	 */
	public void displaySubtask(String message) {
		if ((message == null) || (message.equals(""))) { //$NON-NLS-1$
			return;
		}

		if (getProgressMonitor() != null) {
			getProgressMonitor().subTask(message);
		} else {
			System.out.println(message);
		}
	}

	/**
	 * @see org.eclipse.wst.validation.internal.provisional.core.core.IReporter#getMessages()
	 */
	public List getMessages() {
		return null;
	}

	/**
	 * @see org.eclipse.wst.validation.internal.provisional.core.core.IReporter#isCancelled()
	 */
	public boolean isCancelled() {
		if (getProgressMonitor() != null) {
			return getProgressMonitor().isCanceled();
		}
		return false;
	}

	/**
	 * @see org.eclipse.wst.validation.internal.provisional.core.core.IReporter#addMessage(IValidator, IMessage)
	 */
	public void addMessage(IValidator validator, IMessage message)  {
		IResource resource = getMessageResource(validator, message.getTargetObject());
		IWorkbenchContext helper = null;
		ValidatorMetaData vmd = getVMD(validator);
		try {
			helper = getHelper(validator);
		} catch (InstantiationException exc) {
			try {
				// Unlikely that an exception will be thrown, because this method is
				// invoked by the validator, and if the validator is invoked, it's likely
				// that the helper has been loaded too
				
				
				// Remove the vmd from the reader's list
				ValidationRegistryReader.getReader().disableValidator(vmd);

				// Log the reason for the disabled validator
				Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
				if (logger.isLoggingLevel(Level.SEVERE)) {
					LogEntry entry = ValidationPlugin.getLogEntry();
					entry.setSourceID("WorkbenchReporter::addMessage(IValidator, IMessage)"); //$NON-NLS-1$
					entry.setTargetException(exc);
					logger.write(Level.SEVERE, entry);
				}
				return;
			} catch (IllegalArgumentException exc2) {
				logDisabledValidator(exc2);
				return;
			}
		} catch (IllegalArgumentException exc) {
			logDisabledValidator(exc);
			return;
		}

		if (resource == null) {
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.FINE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter.addMessage(IValidator, Message)"); //$NON-NLS-1$
				entry.setMessageTypeIdentifier(ResourceConstants.VBF_EXC_INVALID_RESOURCE);
				String result = MessageFormat.format(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_EXC_INVALID_RESOURCE), new String[]{message.getText(), getTargetObjectName(helper, message)});
				entry.setText(result);				
				//entry.setTokens(new String[]{message.getText(), getTargetObjectName(helper, message)});
				logger.write(Level.FINE, entry);
			}
			return;
		}

		if( validator instanceof IValidatorJob ){
			cacheMessage( (IValidatorJob)validator, resource, validator.getClass(), message, getTargetObjectName(helper, message), getLocation(helper, message), getMarkerId(vmd, message) );
		}else
			addMessage(resource, validator.getClass(), message, getTargetObjectName(helper, message), getLocation(helper, message),getMarkerId(vmd,message));
	}

	private String getMarkerId(ValidatorMetaData vmd, IMessage message) {
		if (vmd.getMarkerIds() != null) {
			if (vmd.getMarkerIds().length == 1)
				return vmd.getMarkerIds()[0];
			else if (vmd.getMarkerIds().length > 1) {
				String messageMarkerId = message.getMarkerId();
				if (messageMarkerId != null && messageMarkerId.length() > 0) {
					String firstMarkerId = vmd.getMarkerIds()[0];
					String pluginQualifier = firstMarkerId.substring(0, firstMarkerId.lastIndexOf("."));
					String qualifiedMessageMarkerId = null;
					if (messageMarkerId.indexOf(pluginQualifier) == -1)
						qualifiedMessageMarkerId = pluginQualifier + "." + messageMarkerId;
					else
						qualifiedMessageMarkerId = messageMarkerId;
					if (Arrays.asList(vmd.getMarkerIds()).contains(qualifiedMessageMarkerId))
						return qualifiedMessageMarkerId;
				}
			}
		}
		return null;
	}

	private void logDisabledValidator(IllegalArgumentException exc) {
		// Even the IValidator is invalid. Unfortunately, can't disable the
		// validator because it can't be found by the registry reader.
		// Log the reason for the disabled validator
		Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
		if (logger.isLoggingLevel(Level.SEVERE)) {
			LogEntry entry = ValidationPlugin.getLogEntry();
			entry.setSourceID("WorkbenchReporter::addMessage(IValidator, IMessage)"); //$NON-NLS-1$
			entry.setTargetException(exc);
			logger.write(Level.SEVERE, entry);
		}
		return;
	}

	/**
	 * @see org.eclipse.wst.validation.internal.provisional.core.core.IReporter#displaySubtask(IValidator, IMessage)
	 */
	public void displaySubtask(IValidator validator, IMessage message) {
		if ((message == null) || (message.equals(""))) { //$NON-NLS-1$
			return;
		}

		displaySubtask(message.getText(validator.getClass().getClassLoader()));
	}

	/**
	 * @see org.eclipse.wst.validation.internal.provisional.core.core.IReporter#removeAllMessages(IValidator)
	 */
	public void removeAllMessages(IValidator validator) {
		if (validator == null) { // getHelper could be null if the user cancelled before something
			// was fully initialized
			return;
		}

		removeAllMessages(validator, null);
	}

	/**
	 * @see org.eclipse.wst.validation.internal.provisional.core.core.IReporter#removeAllMessages(IValidator, Object)
	 */
	public void removeAllMessages(IValidator validator, Object object) {
		IResource resource = getMessageResource(validator, object);
		if (resource == null) {
			return;
		}

		ValidatorMetaData vmd = ValidationRegistryReader.getReader().getValidatorMetaData(validator);
		if (vmd == null) {
			return;
		}

		IWorkbenchContext helper = null;
		try {
			//helper = vmd.getHelper(resource.getProject());
			helper = getHelper(validator);
		} catch (InstantiationException exc) {
			// Unlikely that an exception will be thrown, because this method is
			// invoked by the validator, and if the validator is invoked, it's likely
			// that the helper has been loaded too.

			// Remove the vmd from the reader's list
			ValidationRegistryReader.getReader().disableValidator(vmd);

			// Log the reason for the disabled validator
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter::removeAllMessages(IResource, IValidator, Object)"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}

			return;
		}

		String[] validatorNames = vmd.getValidatorNames();
		String targetObjectName = getTargetObjectName(helper, object);
		removeAllMessages(resource, validatorNames, targetObjectName);
	}

	/**
	 * @see org.eclipse.wst.validation.internal.provisional.core.core.IReporter#removeMessageSubset(IValidator, Object, String)
	 */
	public void removeMessageSubset(IValidator validator, Object obj, String groupName) {
		IResource resource = getMessageResource(validator, obj);
		if (resource == null) {
			return;
		}

		ValidatorMetaData vmd = ValidationRegistryReader.getReader().getValidatorMetaData(validator);
		if (vmd == null) {
			return;
		}


		IWorkbenchContext helper = null;
		try {
			//helper = vmd.getHelper(resource.getProject());
			helper = getHelper( resource.getProject(), validator );
		} 
		catch (InstantiationException exc) {
			// Unlikely that an exception will be thrown, because this method is
			// invoked by the validator, and if the validator is invoked, it's likely
			// that the helper has been loaded too.

			// Remove the vmd from the reader's list
			ValidationRegistryReader.getReader().disableValidator(vmd);

			// Log the reason for the disabled validator
			Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
			if (logger.isLoggingLevel(Level.SEVERE)) {
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setSourceID("WorkbenchReporter::removeAllMessages(IResource, IValidator, Object)"); //$NON-NLS-1$
				entry.setTargetException(exc);
				logger.write(Level.SEVERE, entry);
			}

			return;
		}

		String[] validatorNames = vmd.getValidatorNames();
		String targetObjectName = getTargetObjectName(helper, obj);
		removeMessageSubset(resource, validatorNames, targetObjectName, groupName);
	}
	
	private static void cacheMessage( IValidatorJob validator,
				IResource resource,
				Class clazz, IMessage message,
				String targetObjectName,
				String location,
				String markerId ){
		
		if ((clazz == null) || (message == null) || (resource == null)) {
			return;
		}
		ClassLoader cl = null;
		if (cl == null) {
			cl = clazz.getClassLoader();
		}
		String text = message.getText(cl);
		MessageInfo msgInfo = new MessageInfo(getUniqueId(clazz), resource, location,
					text, targetObjectName, markerId, message );

		ValidatorManager mgr = ValidatorManager.getManager();
		mgr.cacheMessage( validator, msgInfo );
	}
}