package de.uniba.dsg.bpmnspector.common.util; import api.ValidationResult; import api.Violation; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.apache.velocity.exception.VelocityException; import org.apache.velocity.runtime.RuntimeConstants; import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** * @author Matthias Geiger * @version 1.0 */ public class HtmlReportGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(HtmlReportGenerator.class .getSimpleName()); public static Path createHtmlReport(ValidationResult result) { String fileName = result.getFoundFiles().get(0).getFileName().toString(); try { Path reportPath = FileUtils.createResourcesForReports(); Path htmlFile = FileUtils.createFileForReport(reportPath, fileName, "html"); createReportFromValidationResult(result, htmlFile); return htmlFile; } catch ( IOException ioe) { LOGGER.error("Creation of HTML Report files failed. Report directory or needed resources could not be created.", ioe); return null; } } public static Path createSummaryReport(List<ValidationResult> results, Path baseFolder) { String fileName = "ValidationSummary"+(new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault()).format(new Date()))+".html"; try { Path reportPath = FileUtils.createResourcesForReports(); Path summaryFile = reportPath.resolve(fileName); int checkedFilesSum = 0; int validResults = 0; List<SingleValidationSummary> summaries = new LinkedList<>(); Map<String, Integer> violationsByConstraintCount = new TreeMap<>(); for(ValidationResult singleResult : results) { //create Report Path singleReport = createHtmlReport(singleResult); // update counters checkedFilesSum += singleResult.getFoundFiles().size(); if(singleResult.isValid()) { validResults++; } // update violationsByConstraintCount addViolationsToMap(singleResult, violationsByConstraintCount); //create summary for single validation result SingleValidationSummary summary = new SingleValidationSummary(singleReport.getFileName().toString(), singleResult.getFoundFiles().get(0).toString(), singleResult.getViolations().size(), singleResult.getWarnings().size()); summaries.add(summary); } createSummaryHtml(baseFolder.toString(), summaryFile, checkedFilesSum, validResults, violationsByConstraintCount, summaries); return summaryFile; } catch ( IOException ioe) { LOGGER.error("Creation of HTML Report files failed. Report directory or needed resources could not be created.", ioe); return null; } } private static void createSummaryHtml(String baseFolder, Path summaryFile, int checkedFilesSum, int validResults, Map<String, Integer> violationsByConstraintCount, List<SingleValidationSummary> summaries) { Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); Velocity.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); Velocity.init(); try { Template template = Velocity.getTemplate("reporting/ValidationSummary.vm"); VelocityContext context = new VelocityContext(); context.put("baseFolder", baseFolder); context.put("checkedFilesSum", checkedFilesSum); context.put("directlyChecked", summaries.size()); context.put("importedFilesChecked", checkedFilesSum-summaries.size()); context.put("validResults", validResults); context.put("invalidResults", summaries.size()-validResults); context.put("violationsByConstraintCount", violationsByConstraintCount); context.put("summaries", summaries); StringWriter sw = new StringWriter(); template.merge(context, sw); try (FileWriter fw = new FileWriter(summaryFile.toFile())) { fw.write(sw.toString()); fw.flush(); } catch (IOException ioe) { LOGGER.error("Creation of HTML Report file {} failed.", summaryFile.toString(), ioe); } } catch (VelocityException e) { LOGGER.error("Creation of HTML report failed due to a Velocity Exception", e); } } private static void addViolationsToMap(ValidationResult singleResult, Map<String, Integer> violationsByConstraintCount) { for(Violation violation : singleResult.getViolations()) { Integer i = violationsByConstraintCount.get(violation.getConstraint()); if (i == null) { violationsByConstraintCount.put(violation.getConstraint(), 1); } else { violationsByConstraintCount.put(violation.getConstraint(), i + 1); } } } private static void createReportFromValidationResult(ValidationResult result, Path outputPath) { Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); Velocity.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); Velocity.init(); try { Template template = Velocity.getTemplate("reporting/ValidationResult.vm"); VelocityContext context = new VelocityContext(); context.put("validationResult", result); context.put("resourcesWithWarnings", getResourcesWithWarnings(result)); StringWriter sw = new StringWriter(); template.merge(context, sw); try (FileWriter fw = new FileWriter(outputPath.toFile())) { fw.write(sw.toString()); fw.flush(); } catch (IOException ioe) { LOGGER.error("Creation of HTML Report file {} failed.", outputPath.toString(), ioe); } } catch (VelocityException e) { LOGGER.error("Creation of HTML report failed due to a Velocity Exception", e); } } private static List<String> getResourcesWithWarnings(ValidationResult result) { return result.getWarnings().stream().map(v -> v.getLocation().getResource().getResourceName()).distinct().collect(Collectors.toList()); } public static class SingleValidationSummary { private final String reportFilename; private final String checkedFilename; private final int violationCount; private final int warningCount; public SingleValidationSummary(String reportFilename, String checkedFilename, int violationCount, int warningCount) { this.reportFilename = reportFilename; this.checkedFilename = checkedFilename; this.violationCount = violationCount; this.warningCount = warningCount; } public String getReportFilename() { return reportFilename; } public String getCheckedFilename() { return checkedFilename; } public int getViolationCount() { return violationCount; } public int getWarningCount() { return warningCount; } } }