src/main/java/com/sleekbyte/tailor/format/HTMLFormatter.java
package com.sleekbyte.tailor.format;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.sleekbyte.tailor.common.ColorSettings;
import com.sleekbyte.tailor.common.ConfigProperties;
import com.sleekbyte.tailor.common.Messages;
import com.sleekbyte.tailor.output.ViolationMessage;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Formatter that displays violation messages in valid HTML output.
*/
public final class HTMLFormatter extends Formatter {
protected static final String TEMPLATE_PATH = "index.html";
private static final String NEWLINE_PATTERN = "\n";
private static final List<Map<String, Object>> FILES = new ArrayList<>();
public HTMLFormatter(ColorSettings colorSettings) {
super(colorSettings);
}
protected static List<Map<String, Object>> getFiles() {
return FILES;
}
protected static void clearFiles() {
FILES.clear();
}
@Override
public void displayViolationMessages(List<ViolationMessage> violationMessages, File inputFile) throws IOException {
List<Map<String, Object>> violations = new ArrayList<>();
for (ViolationMessage msg : violationMessages) {
Map<String, Object> violation = new HashMap<>();
Map<String, Integer> location = new HashMap<>();
location.put(Messages.LINE_KEY, msg.getLineNumber());
if (msg.getColumnNumber() != 0) {
location.put(Messages.COLUMN_KEY, msg.getColumnNumber());
}
violation.put(Messages.LOCATION_KEY, location);
switch (msg.getSeverity()) {
case ERROR:
violation.put(Messages.ERROR, true);
break;
case WARNING:
violation.put(Messages.WARNING, true);
break;
default:
break;
}
violation.put(Messages.RULE_KEY, msg.getRule().getName());
violation.put(Messages.MESSAGE_KEY, msg.getMessage());
violations.add(violation);
}
storeMessages(violations, true, inputFile.getCanonicalPath());
}
@Override
public void displayParseErrorMessage(File inputFile) throws IOException {
storeMessages(new ArrayList<>(), false, inputFile.getCanonicalPath());
}
@Override
public void displaySummary(long numFiles, long numSkipped, long numErrors, long numWarnings) throws IOException {
Map<String, Object> output = new HashMap<>();
output.put(Messages.SUMMARY_KEY,
Formatter.formatSummary(numFiles, numSkipped, numErrors, numWarnings).replace(NEWLINE_PATTERN, ""));
// Sort files by descending order of the number of violations
FILES.sort((o1, o2) ->
((List) o2.get(Messages.VIOLATIONS_KEY)).size() - ((List) o1.get(Messages.VIOLATIONS_KEY)).size());
output.put(Messages.FILES_KEY, FILES);
output.put(Messages.VERSION_LONG_OPT, new ConfigProperties().getVersion());
InputStreamReader inputStreamReader = new InputStreamReader(
HTMLFormatter.class.getResourceAsStream(TEMPLATE_PATH),
Charset.defaultCharset());
Mustache mustache = new DefaultMustacheFactory().compile(inputStreamReader, TEMPLATE_PATH);
mustache.execute(new OutputStreamWriter(System.out, Charset.defaultCharset()), output).flush();
inputStreamReader.close();
}
@Override
public void printProgressInfo(String str) {
// Not Applicable to this formatter
}
private void storeMessages(List<Map<String, Object>> violations, boolean parsed, String filePath)
throws IOException {
Map<String, Object> output = new HashMap<>();
output.put(Messages.PATH_KEY, filePath);
output.put(Messages.VIOLATIONS_KEY, violations);
final int numViolations = violations.size();
output.put(Messages.NUM_VIOLATIONS_KEY,
Formatter.pluralize(numViolations, Messages.SINGLE_VIOLATION_KEY, Messages.MULTI_VIOLATIONS_KEY)
);
output.put(Messages.PARSED_KEY, parsed);
FILES.add(output);
}
}