package jetbrains.buildServer.tools.errors;
import jetbrains.buildServer.tools.ErrorKind;
import jetbrains.buildServer.tools.LazyMap;
import jetbrains.buildServer.tools.MultiMap;
import jetbrains.buildServer.tools.ScanFile;
import jetbrains.buildServer.tools.rules.PathRule;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* Created 03.07.13 21:00
*
* @author Eugene Petrenko (eugene.petrenko@jetbrains.com)
*/
public class ReportErrors {
private final PathsCalculator myPaths;
private final MultiMap<String, String> myGenericErrorsMessageToFile = new MultiMap<String, String>();
private final MultiMap<String, String> myCheckErrorToFile = new MultiMap<String, String>();
private final LazyMap<ErrorKind, ReportKindError> myCheckErrors = new LazyMap<ErrorKind, ReportKindError>() {
@NotNull
@Override
protected ReportKindError computeValue(@NotNull ErrorKind errorKind) {
return new ReportKindError(myPaths, errorKind);
}
};
public ReportErrors(@NotNull PathsCalculator paths) {
myPaths = paths;
}
public void addCheckError(@NotNull final ScanFile file,
@NotNull final ErrorKind kind,
@NotNull final String shortError,
@NotNull final String message) {
myCheckErrors.get(kind).addCheckError(file, message);
myCheckErrorToFile.putValue(shortError, myPaths.path(file));
}
public void addGenericError(@NotNull final ScanFile file,
@NotNull final String message) {
myGenericErrorsMessageToFile.putValue(message, myPaths.path(file));
}
public void addRuleError(@NotNull final PathRule rule,
@NotNull final String message) {
myGenericErrorsMessageToFile.putValue(message, myPaths.path(rule.getPath()));
}
public void render(@NotNull RenderMode mode, @NotNull final LogWriter writer) {
writer.println("Total errors: " + getNumberOfErrors());
writer.println();
writer.println();
if (!myGenericErrorsMessageToFile.isEmpty()) {
writer.println("Generic errors (" + myGenericErrorsMessageToFile.getValuesSize() + "):");
renderGenericErrors(writer.offset());
writer.println();
}
if (mode == RenderMode.SHORT && !myCheckErrorToFile.isEmpty()) {
final int top = 100;
writer.println("Top " + top + " errors: ");
renderTopErrors(writer, top);
writer.println();
}
if (!myCheckErrors.isEmpty()) {
writer.println("Check errors (" + getNumberOfCheckErrors() + "):");
renderCheckErrors(mode, writer.offset());
writer.println();
}
}
private void renderTopErrors(@NotNull final LogWriter writer, final int top) {
final LogWriter offset = writer.offset();
final List<String> keys = new ArrayList<String>(myCheckErrorToFile.keySet());
Collections.sort(keys, new Comparator<String>() {
public int compare(@NotNull String o1, @NotNull String o2) {
int c1 = myCheckErrorToFile.get(o1).size();
int c2 = myCheckErrorToFile.get(o2).size();
if (c1 < c2) return 1;
if (c1 > c2) return -1;
return o1.compareToIgnoreCase(o2);
}
});
final Iterator<String> it = keys.iterator();
for(int i = 0; i < top && it.hasNext(); i++) {
String err = it.next();
offset.println(err + " (" + myCheckErrorToFile.get(err).size() + ")");
}
}
private void renderCheckErrors(@NotNull final RenderMode mode, @NotNull final LogWriter writer) {
for (ReportKindError e : myCheckErrors.values()) {
e.render(mode, writer);
}
}
private void renderGenericErrors(@NotNull final LogWriter writer) {
for (Map.Entry<String, List<String>> e : myGenericErrorsMessageToFile.entrySet()) {
writer.println(e.getKey());
final LogWriter offset = writer.offset();
for (String err : e.getValue()) {
offset.println(err);
}
}
}
public boolean hasErrors() {
return !myGenericErrorsMessageToFile.isEmpty() || !myCheckErrors.isEmpty();
}
public int getNumberOfErrors() {
return myGenericErrorsMessageToFile.getValuesSize() + getNumberOfCheckErrors();
}
public int getNumberOfCheckErrors() {
int sz = 0;
for (ReportKindError error : myCheckErrors.values()) {
sz += error.getNumberOfErrors();
}
return sz;
}
}