package net.sourceforge.pmd.eclipse.runtime.builder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.eclipse.plugin.PMDPlugin;
import net.sourceforge.pmd.eclipse.runtime.PMDRuntimeConstants;
import net.sourceforge.pmd.eclipse.ui.PMDUiConstants;
import net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord;
import net.sourceforge.pmd.eclipse.ui.model.FileRecord;
import net.sourceforge.pmd.eclipse.ui.model.MarkerRecord;
import net.sourceforge.pmd.eclipse.ui.model.RootRecord;
import net.sourceforge.pmd.util.StringUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
/**
*
* @author Brian Remedios
*/
public class MarkerUtil {
public static final IMarker[] EMPTY_MARKERS = new IMarker[0];
private static Map<String, Rule> rulesByName;
private MarkerUtil() { }
public static boolean hasAnyRuleMarkers(IResource resource) throws CoreException {
final boolean[] foundOne = new boolean[] { false };
IResourceVisitor ruleMarkerFinder = new IResourceVisitor() {
public boolean visit(IResource resource) {
if (foundOne[0]) return false;
if (resource instanceof IFile) {
for (String markerType : PMDRuntimeConstants.RULE_MARKER_TYPES) {
IMarker[] ruleMarkers = null;
try {
ruleMarkers = resource.findMarkers(markerType, true, IResource.DEPTH_INFINITE);
} catch (CoreException ex) {
// what do to?
}
if (ruleMarkers != null && ruleMarkers.length > 0) {
foundOne[0] = true;
return false;
}
}
}
return true;
}
};
try {
resource.accept(ruleMarkerFinder);
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return foundOne[0];
}
private static IProject projectFor(IResource resource) {
if (resource instanceof IWorkspaceRoot) return null;
if (resource instanceof IProject) return (IProject)resource;
return projectFor(resource.getParent());
}
public static Set<IProject> commonProjectsOf(IMarker[] markers) {
Set<IProject> projects = new HashSet<IProject>();
for (IMarker marker : markers) {
IProject project = projectFor(marker.getResource());
if (project != null) projects.add(project);
}
return projects;
}
public static String ruleNameFor(IMarker marker) {
return marker.getAttribute(PMDUiConstants.KEY_MARKERATT_RULENAME, "");
}
public static int rulePriorityFor(IMarker marker) throws CoreException {
return (Integer)marker.getAttribute(PMDUiConstants.KEY_MARKERATT_PRIORITY);
}
public static String messageFor(IMarker marker, String defaultValue) {
return marker.getAttribute(IMarker.MESSAGE, defaultValue);
}
public static Long createdOn(IMarker marker, long onErrorValue) {
try {
return (Long)marker.getCreationTime();
} catch (CoreException ce) {
return onErrorValue;
}
}
public static int rulePriorityFor(IMarker marker, int defaultValue) {
return marker.getAttribute(PMDUiConstants.KEY_MARKERATT_PRIORITY, defaultValue);
}
public static boolean doneState(IMarker marker, boolean defaultValue) {
return marker.getAttribute(IMarker.DONE, defaultValue);
}
public static int deleteViolationsOf(String ruleName, IResource resource) {
try {
IMarker[] markers = findAllMarkers(resource);
if (markers.length == 0) return 0;
List<IMarker> matches = new ArrayList<IMarker>(markers.length);
for (IMarker marker : markers) {
String name = ruleNameFor(marker);
if (ruleName.equals(name)) {
matches.add(marker);
}
}
markers = new IMarker[matches.size()];
matches.toArray(markers);
resource.getWorkspace().deleteMarkers(markers);
return markers.length;
} catch (CoreException ex) {
return 0;
}
}
public static List<IMarkerDelta> markerDeltasIn(IResourceChangeEvent event) {
List<IMarkerDelta> deltas = new ArrayList<IMarkerDelta>();
for (String markerType : PMDRuntimeConstants.RULE_MARKER_TYPES) {
IMarkerDelta[] deltaArray = event.findMarkerDeltas(markerType, true);
for (IMarkerDelta delta : deltaArray) deltas.add(delta);
}
return deltas;
}
public static List<Rule> rulesFor(IMarker[] markers) {
List<Rule> rules = new ArrayList<Rule>(markers.length);
RuleSet ruleset = PMDPlugin.getDefault().getPreferencesManager().getRuleSet();
for (IMarker marker : markers) {
String name = ruleNameFor(marker);
if (StringUtil.isEmpty(name)) continue;
Rule rule = ruleset.getRuleByName(name);
if (rule == null) continue;
rules.add(rule);
}
return rules;
}
/**
* Returns the name of the rule that is common to all markers
* or null if any one of them differ.
*
* @param IMarker[] markers
* @return String
*/
public static String commonRuleNameAmong(IMarker[] markers) {
String ruleName = ruleNameFor(markers[0]);
for (int i=1; i<markers.length; i++) {
if (!ruleName.equals(ruleNameFor(markers[i]))) return null;
}
return ruleName;
}
public static void deleteAllMarkersIn(IResource resource) throws CoreException {
deleteMarkersIn(resource, PMDRuntimeConstants.ALL_MARKER_TYPES);
}
public static void deleteMarkersIn(IResource resource, String markerType) throws CoreException {
deleteMarkersIn(resource, new String[] {markerType} );
}
public static void deleteMarkersIn(IResource resource, String[] markerTypes) throws CoreException {
for (String markerType : markerTypes) {
resource.deleteMarkers(markerType, true, IResource.DEPTH_INFINITE);
}
PMDPlugin.getDefault().removedMarkersIn(resource);
}
public static IMarker[] findAllMarkers(IResource resource) throws CoreException {
return findMarkers(resource, PMDRuntimeConstants.ALL_MARKER_TYPES);
}
public static IMarker[] findMarkers(IResource resource, String markerType) throws CoreException {
return findMarkers(resource, new String[] { markerType} );
}
public static IMarker[] findMarkers(IResource resource, String[] markerTypes) throws CoreException {
List<IMarker> markerList = new ArrayList<IMarker>();
for (String markerType : markerTypes) {
for (IMarker marker : resource.findMarkers(markerType, true, IResource.DEPTH_INFINITE)) {
markerList.add(marker);
}
}
IMarker[] markerArray = new IMarker[markerList.size()];
return markerList.toArray(markerArray);
}
public static Set<Integer> priorityRangeOf(IResource resource, String[] markerTypes, int sizeLimit) throws CoreException {
Set<Integer> priorityLevels = new HashSet<Integer>(sizeLimit);
for (String markerType : markerTypes) {
for (IMarker marker : resource.findMarkers(markerType, true, IResource.DEPTH_INFINITE)) {
priorityLevels.add( rulePriorityFor(marker) );
if (priorityLevels.size() == sizeLimit) return priorityLevels;
}
}
return priorityLevels;
}
public static Set<String> currentRuleNames() {
gatherRuleNames();
return rulesByName.keySet();
}
private static void gatherRuleNames() {
rulesByName = new HashMap<String, Rule>();
Set<RuleSet> ruleSets = PMDPlugin.getDefault().getRuleSetManager().getRegisteredRuleSets();
for (RuleSet rs : ruleSets) {
for (Rule rule : rs.getRules()) {
rulesByName.put(rule.getName(), rule);
}
}
}
private static Rule ruleFrom(IMarker marker) {
String ruleName = marker.getAttribute(PMDRuntimeConstants.KEY_MARKERATT_RULENAME, "");
if (StringUtil.isEmpty(ruleName)) return null; //printValues(marker);
return rulesByName.get(ruleName);
}
public static Set<IFile> allMarkedFiles(RootRecord root) {
gatherRuleNames();
Set<IFile> files = new HashSet<IFile>();
for (AbstractPMDRecord projectRecord : root.getChildren()) {
for (AbstractPMDRecord packageRecord : projectRecord.getChildren()) {
for (AbstractPMDRecord fileRecord : packageRecord.getChildren()) {
((FileRecord)fileRecord).updateChildren();
for (AbstractPMDRecord mRecord : fileRecord.getChildren()) {
MarkerRecord markerRecord = (MarkerRecord) mRecord;
for (IMarker marker : markerRecord.findMarkers()) {
Rule rule = ruleFrom(marker);
if (rule == null) continue;
files.add((IFile)fileRecord.getResource());
break;
}
}
}
}
}
return files;
}
}