blob: dcc3c5a2f6fa660a304c971d1987219c57e25425 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2005 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.html.internal.validation;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
/**
* This class must be called only by the validation framework.
*
* This singleton interacts with the eclipse workbench's Task list.
* TaskListUtility adds and removes tasks from the list.
*
* This class must not be called outside of an IWorkspaceRunnable or
* IRunnableWithProgress. Many resource deltas can be generated by the methods
* in this class.
*
* This came from TaskListUtility
*/
public class TaskListUtility {
// private static final String PLUGIN_ID = ValidationPlugin.PLUGIN_ID;
private static final String PLUGIN_ID = HTMLUIPlugin.ID;
private static final String VALIDATION_MARKER = PLUGIN_ID + ".problemmarker"; //$NON-NLS-1$ // The extension which is used to add validation markers to the task list
private static final String VALIDATION_MARKER_OWNER = "owner"; //$NON-NLS-1$ // The IValidator who owns the IMarker on the task list
private static final String VALIDATION_MARKER_SEVERITY = "validationSeverity"; //$NON-NLS-1$ // one of the IMessage values
private static final String VALIDATION_MARKER_TARGETOBJECT = "targetObject"; //$NON-NLS-1$ // When more than one target object resolves to the same IResource, this field identifies which targetObject owns a particular message.
private static final String VALIDATION_MARKER_GROUP = "groupName"; //$NON-NLS-1$ // For incremental validation, this field associates a message with a group, so that a subset of messages may be removed from a file.
private static final String VALIDATION_MARKER_MESSAGEID = "messageId"; //$NON-NLS-1$ // Persist the message id of the message, not just the translated text.
private static final int DEPTH_INFINITE = IResource.DEPTH_INFINITE;
private static final int DEPTH_ZERO = IResource.DEPTH_ZERO;
private final static IMarker[] NO_MARKERS = new IMarker[0];
/**
* This method adds a message to a resource in the task list.
*/
public static IMarker addTask(String pluginId, IResource resource, String location, String messageId, String message, int markerType, String targetObjectName, String groupName, int offset, int length) throws CoreException {
if ((message == null) || (resource == null)) {
return null;
}
int severity = getSeverity(markerType);
// Allow duplicate entries in the task list.
// Prior to a full validation, the validation framework will remove
// all messages owned
// by a validator before it is executed.
// Prior to an incremental validation, the validation framework will
// remove all messages,
// on each of the changed resources, owned by a validator before it is
// invoked.
//
// It is up to the validator to make sure that it is not adding the
// same message
// in more than one place, and also to clear out any old messages
// which are not cleared
// by the validation framework.
IMarker item = resource.createMarker(VALIDATION_MARKER); // add a
// validation
// marker
// For performance reasons, replace the multiple setAttribute
// calls above with a single setAttributes call.
boolean offsetSet = ((offset != IMessage.OFFSET_UNSET) && (length != IMessage.OFFSET_UNSET));
int size = (offsetSet) ? 10 : 8; // add CHAR_START, CHAR_END only
// if the offset is set. If the
// offset is set, it takes
// precendence over the line
// number. (eclipse's rule, not
// mine.)
String[] attribNames = new String[size];
Object[] attribValues = new Object[size];
// Very first thing, add the owner. That way, if the code dies
// before things are persisted, hopefully this marker will be
// persisted.
// Hopefully, eclipse WILL persist this field, as requested.
attribNames[0] = VALIDATION_MARKER_OWNER;
attribValues[0] = pluginId;
attribNames[1] = VALIDATION_MARKER_SEVERITY; // this validation
// severity is stored,
// in addition to the
// marker severity, to
// enable more than
// one severity of
// message to be
// displayed. e.g.
// ERROR | WARNING
// (using binary OR).
// The IMarker
// constants are
// regular decimal
// constants.
attribValues[1] = new Integer(markerType);
attribNames[2] = VALIDATION_MARKER_TARGETOBJECT; // to distinguish
// between
// messages which
// are registered
// on an
// IResource, but
// against
// different
// target objects
attribValues[2] = ((targetObjectName == null) ? "" : targetObjectName); //$NON-NLS-1$
attribNames[3] = VALIDATION_MARKER_GROUP;
attribValues[3] = ((groupName == null) ? "" : groupName); //$NON-NLS-1$
attribNames[4] = IMarker.MESSAGE;
attribValues[4] = message;
attribNames[5] = VALIDATION_MARKER_MESSAGEID;
attribValues[5] = messageId;
attribNames[6] = IMarker.SEVERITY; // IMarker.SEVERITY_ERROR,
// IMarker.SEVERITY_WARNING,
// IMarker.SEVERITY_INFO
attribValues[6] = new Integer(severity);
try {
// If the location is a line number, store it as a line number
Integer lineNumber = Integer.valueOf(location);
attribNames[7] = IMarker.LINE_NUMBER;
attribValues[7] = lineNumber;
}
catch (NumberFormatException exc) {
// Otherwise, store it as a text location
attribNames[7] = IMarker.LOCATION;
attribValues[7] = location;
}
if (offsetSet) {
attribNames[8] = IMarker.CHAR_START;
attribValues[8] = new Integer(offset);
attribNames[9] = IMarker.CHAR_END;
attribValues[9] = new Integer(offset + length);
}
item.setAttributes(attribNames, attribValues);
return item;
}
/**
* Given one of the SeverityEnum severities, return the IMarker severity
* int that is its equivalent.
*/
private static int getSeverity(int severityEnumValue) {
switch (severityEnumValue) {
case (IMessage.HIGH_SEVERITY) : {
return IMarker.SEVERITY_ERROR;
}
case (IMessage.LOW_SEVERITY) : {
return IMarker.SEVERITY_INFO;
}
case (IMessage.NORMAL_SEVERITY) : {
return IMarker.SEVERITY_WARNING;
}
case (IMessage.ALL_MESSAGES) :
case (IMessage.ERROR_AND_WARNING) :
default : {
// assume it's a warning.
return IMarker.SEVERITY_WARNING;
}
}
}
private static int getDepth(IResource resource) {
if (resource instanceof IProject) {
return DEPTH_INFINITE; // DEPTH_INFINITE means get this project's
// markers, and the markers belonging to
// the project's children.
}
else if (resource instanceof IWorkspaceRoot) {
// Needed for the ValidationMigrator when it checks for orphan
// tasks.
return DEPTH_INFINITE; // DEPTH_INFINITE means get all of the
// markers in the workspace
}
return DEPTH_ZERO; // DEPTH_ZERO means just this resource, not its
// children
}
private static IMarker[] getValidationTasks(IResource resource, int severity, int depth) {
IMarker[] tempMarkers = null;
int validCount = 0;
try {
IMarker[] allMarkers = null;
try {
allMarkers = resource.findMarkers(VALIDATION_MARKER, false, depth); // false
// means
// only
// consider
// PROBLEM_MARKER,
// not
// variants
// of
// PROBLEM_MARKER.
// Since
// addTask
// only
// adds
// PROBLEM_MARKER,
// we
// don't
// need
// to
// consider
// its
// subtypes.
}
catch (CoreException exc) {
// Logger logger =
// ValidationPlugin.getPlugin().getMsgLogger();
// if (logger.isLoggingLevel(Level.SEVERE)) {
// LogEntry entry = ValidationPlugin.getLogEntry();
// entry.setSourceID("TaskListUtility.getValidationTasks(IResource,
// int)"); //$NON-NLS-1$
// entry.setTargetException(exc);
// logger.write(Level.SEVERE, entry);
// }
return NO_MARKERS;
}
// Now filter in the markers, based on severity type.
if (allMarkers.length != 0) {
tempMarkers = new IMarker[allMarkers.length];
for (int i = 0; i < allMarkers.length; i++) {
IMarker marker = allMarkers[i];
Integer filterSeverity = (Integer) marker.getAttribute(VALIDATION_MARKER_SEVERITY);
if (filterSeverity == null) {
// odd...marker wasn't created correctly. How could
// this happen?
// Default to the current severity and add it to the
// list.
try {
marker.setAttribute(IMarker.SEVERITY, getSeverity(severity));
}
catch (CoreException exc) {
// Logger logger =
// ValidationPlugin.getPlugin().getMsgLogger();
// if (logger.isLoggingLevel(Level.SEVERE)) {
// LogEntry entry =
// ValidationPlugin.getLogEntry();
// entry.setSourceID("TaskListUtility.getValidationTasks(int,
// IResource, int)"); //$NON-NLS-1$
// entry.setTargetException(exc);
// logger.write(Level.SEVERE, entry);
// }
continue;
}
catch (Throwable exc) {
// Logger logger =
// ValidationPlugin.getPlugin().getMsgLogger();
// if (logger.isLoggingLevel(Level.SEVERE)) {
// LogEntry entry =
// ValidationPlugin.getLogEntry();
// entry.setSourceID("TaskListUtility.getValidationTasks(int,
// IResource, int)"); //$NON-NLS-1$
// entry.setTargetException(exc);
// logger.write(Level.SEVERE, entry);
// }
continue;
}
}
else if ((severity & filterSeverity.intValue()) == 0) {
continue;
}
tempMarkers[validCount++] = marker;
}
}
}
catch (CoreException exc) {
// Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
// if (logger.isLoggingLevel(Level.SEVERE)) {
// LogEntry entry = ValidationPlugin.getLogEntry();
// entry.setSourceID("TaskListUtility.getValidationTasks(int,
// IResource, int)"); //$NON-NLS-1$
// entry.setTargetException(exc);
// logger.write(Level.SEVERE, entry);
// }
}
if (validCount == 0) {
return NO_MARKERS;
}
IMarker[] validMarkers = new IMarker[validCount];
System.arraycopy(tempMarkers, 0, validMarkers, 0, validCount);
return validMarkers;
}
private static IMarker[] getValidationTasks(IResource resource, String[] messageOwners, int depth) {
IMarker[] markers = getValidationTasks(resource, IMessage.ALL_MESSAGES, depth);
if (markers.length == 0) {
return NO_MARKERS;
}
IMarker[] temp = new IMarker[markers.length];
int validCount = 0;
for (int i = 0; i < markers.length; i++) {
IMarker marker = markers[i];
try {
Object owner = marker.getAttribute(VALIDATION_MARKER_OWNER);
if ((owner == null) || !(owner instanceof String)) {
// The ValidationMigrator will remove any "unowned"
// validation markers.
continue;
}
for (int j = 0; j < messageOwners.length; j++) {
String messageOwner = messageOwners[j];
if (((String) owner).equals(messageOwner)) {
temp[validCount++] = marker;
break;
}
}
}
catch (CoreException exc) {
// Logger logger =
// ValidationPlugin.getPlugin().getMsgLogger();
// if (logger.isLoggingLevel(Level.SEVERE)) {
// LogEntry entry = ValidationPlugin.getLogEntry();
// entry.setSourceID("TaskListUtility.getValidationTasks(project,
// String[])"); //$NON-NLS-1$
// entry.setTargetException(exc);
// logger.write(Level.SEVERE, entry);
// }
return NO_MARKERS;
}
}
IMarker[] result = new IMarker[validCount];
System.arraycopy(temp, 0, result, 0, validCount);
return result;
}
/**
* This method retrieves all validation tasks from the resource. If depth
* is INFINITE, child tasks are returned as well. Only the tasks which are
* owned by the specified messageOwner, and apply to the named IMessage's
* target object (objectName) will be returned.
*/
private static IMarker[] getValidationTasks(IResource resource, String[] messageOwner, String objectName, String groupName, int depth) throws CoreException {
if ((messageOwner == null) || (resource == null)) {
return NO_MARKERS;
}
int validCount = 0;
IMarker[] validList = null;
IMarker[] markers = getValidationTasks(resource, messageOwner, depth);
if (markers != null) {
validList = new IMarker[markers.length];
for (int i = 0; i < markers.length; i++) {
IMarker marker = markers[i];
// If more than one target object resolves to the same
// resource, removing one target's
// messages should not remove the other target object's
// messages.
if (objectName != null) {
Object targetObject = marker.getAttribute(VALIDATION_MARKER_TARGETOBJECT);
if ((targetObject == null) || !(targetObject instanceof String) || !(((String) targetObject).equals(objectName))) {
continue;
}
}
if (groupName != null) {
Object group = marker.getAttribute(VALIDATION_MARKER_GROUP);
if ((group == null) || !(group instanceof String) || !(((String) group).equals(groupName))) {
continue;
}
}
validList[validCount++] = marker;
}
}
if (validCount == 0) {
return NO_MARKERS;
}
IMarker[] result = new IMarker[validCount];
System.arraycopy(validList, 0, result, 0, validCount);
return result;
}
/**
* This method removes all messages from a resource in the task list.
*/
public static void removeAllTasks(IResource resource, String owner, String objectName) throws CoreException {
removeAllTasks(resource, new String[]{owner}, objectName);
}
public static void removeAllTasks(IResource resource, String[] owners, String objectName) throws CoreException {
removeAllTasks(resource, owners, objectName, getDepth(resource));
}
protected static void removeAllTasks(IResource resource, String[] owners, String objectName, int depth) throws CoreException {
removeTaskSubset(resource, owners, objectName, null, depth); // null
// means
// no
// group
// name
}
/**
* This method removes a subset of tasks from the project, including child
* tasks. Every task which belongs to the group, identified by groupName,
* will be removed.
*/
protected static void removeTaskSubset(IResource resource, String[] owners, String objectName, String groupName, int depth) throws CoreException {
if ((owners == null) || (resource == null)) {
return;
}
IMarker[] allTasks = getValidationTasks(resource, owners, objectName, groupName, depth);
if (allTasks.length > 0) {
ResourcesPlugin.getWorkspace().deleteMarkers(allTasks);
}
}
}