All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.capitalone.dashboard.utils.CodeQualityMetricsConverter Maven / Gradle / Ivy

package com.capitalone.dashboard.utils;

import com.capitalone.dashboard.model.*;
import com.capitalone.dashboard.model.quality.*;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
public class CodeQualityMetricsConverter implements CodeQualityVisitor {

    private static final String TOTAL_NO_OF_TESTS = "tests";
    private static final String TEST_FAILURES = "test_failures";
    private static final String TEST_ERRORS = "test_errors";
    private static final String TEST_SUCCESS_DENSITY = "test_success_density";

    private static final String BLOCKER_VIOLATIONS = "blocker_violations";
    private static final String CRITICAL_VIOLATIONS = "critical_violations";
    private static final String MAJOR_VIOLCATIONS = "major_violations";
    private static final String VIOLATIONS = "violations";

    private static final String COVERAGE = "coverage";
    private static final String LINE_COVERAGE = "line_coverage";
    private static final String TOTAL_LINES_COVERED = "total_lines_covered";
    private static final String TOTAL_LINES_MISSED = "total_lines_missed";
    private static final String TOTAL_INSTRUCTIONS_COVERED = "total_instructions_covered";
    private static final String TOTAL_INSTRUCTIONS_MISSED = "total_instructions_missed";

    private final CodeQuality quality = new CodeQuality();

    // note for static analysis names are ,,,violations
    // function tests..

    @Override
    public void visit(JunitXmlReport report) {

        int testsPassed = report.getTests() - report.getFailures() - report.getErrors();

        Map> metricsMap = new HashMap<>();
        metricsMap.put(TOTAL_NO_OF_TESTS, Pair.of(report.getTests(), CodeQualityMetricStatus.Ok));
        metricsMap.put(TEST_FAILURES, Pair.of(report.getFailures(), report.getFailures() > 0 ? CodeQualityMetricStatus.Warning : CodeQualityMetricStatus.Ok));
        metricsMap.put(TEST_ERRORS, Pair.of(report.getErrors(), report.getErrors() > 0 ? CodeQualityMetricStatus.Alert : CodeQualityMetricStatus.Ok));
        metricsMap.put(TEST_SUCCESS_DENSITY, Pair.of(testsPassed, CodeQualityMetricStatus.Ok));

        if (null != report.getTimestamp()) {
            long timestamp = Math.max(quality.getTimestamp(), report.getTimestamp().toGregorianCalendar().getTimeInMillis());
            quality.setTimestamp(timestamp);
        }
        quality.setType(CodeQualityType.StaticAnalysis);

        // finally produce the result
        this.sumMetrics(metricsMap);

    }

    @Override
    public void visit(FindBugsXmlReport findBugReport) {
        Map> metricsMap = new HashMap<>();
        metricsMap.put(BLOCKER_VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(CRITICAL_VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(MAJOR_VIOLCATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));

        // loop over all the stuff in the report and accumulate violations.
        if (null != findBugReport.getFiles()) {
            findBugReport.getFiles().stream().forEach(bugFile -> {
                bugFile.getBugCollection().stream().forEach(
                        bugInstance -> {
                            switch (bugInstance.getPriority()) {
                                case Blocker: {
                                    final Pair metricStatusPair = metricsMap.get(BLOCKER_VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Alert);
                                    metricsMap.put(BLOCKER_VIOLATIONS, newPair);
                                    break;
                                }
                                case Critical: {
                                    final Pair metricStatusPair = metricsMap.get(CRITICAL_VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Alert);
                                    metricsMap.put(CRITICAL_VIOLATIONS, newPair);
                                    break;
                                }
                                case Normal: {
                                    final Pair metricStatusPair = metricsMap.get(MAJOR_VIOLCATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Warning);
                                    metricsMap.put(MAJOR_VIOLCATIONS, newPair);
                                    break;
                                }
                                case Low: {
                                    final Pair metricStatusPair = metricsMap.get(VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Warning);
                                    metricsMap.put(VIOLATIONS, newPair);
                                    break;
                                }
                                default:
                                    // not recognised. ignore
                                    break;
                            }
                        }
                );
            });
        }


        // finally produce the result
        this.sumMetrics(metricsMap);
    }

    public void sumMetrics(Map> metricsMap) {
        Set existingMetrics = quality.getMetrics();
        final Map mapOfExistingMetrics = existingMetrics.stream().collect(Collectors.toMap(CodeQualityMetric::getName, Function.identity()));

        metricsMap.forEach((key, value) -> {
            CodeQualityMetric currentValue = mapOfExistingMetrics.get(key);
            CodeQualityMetric newValue = null;
            if (null == currentValue) {
                CodeQualityMetric codeQualityMetric = new CodeQualityMetric();
                codeQualityMetric.setName(key);
                codeQualityMetric.setFormattedValue(String.valueOf(value.getLeft()));
                codeQualityMetric.setValue(Integer.toString(value.getLeft()));
                codeQualityMetric.setStatus(value.getRight());
                newValue = codeQualityMetric;
            } else {
                // do the sum
                quality.getMetrics().remove(currentValue);
                newValue = new CodeQualityMetric(key);
                newValue.setValue(Integer.toString(Integer.parseInt(currentValue.getValue()) + value.getLeft()));
                newValue.setFormattedValue(String.valueOf(Integer.parseInt(currentValue.getValue()) + value.getLeft()));
                int newOrdinal = Math.max(value.getRight().ordinal(), currentValue.getStatus().ordinal());
                newValue.setStatus(CodeQualityMetricStatus.values()[newOrdinal]);
            }
            quality.addMetric(newValue);
        });
    }

    @Override
    public void visit(JacocoXmlReport jacocoXmlReport) {
        Map> metricsMap = new HashMap<>();
        metricsMap.put(TOTAL_LINES_COVERED, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(TOTAL_LINES_MISSED, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(TOTAL_INSTRUCTIONS_COVERED, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(TOTAL_INSTRUCTIONS_MISSED, Pair.of(0, CodeQualityMetricStatus.Ok));

        for (JacocoXmlReport.Counter counter:jacocoXmlReport.getCounters()) {
            switch (counter.getType()) {
                case LINE:
                    metricsMap.put(TOTAL_LINES_COVERED,Pair.of(counter.getCovered(),CodeQualityMetricStatus.Ok));
                    metricsMap.put(TOTAL_LINES_MISSED,Pair.of(counter.getMissed(),CodeQualityMetricStatus.Ok));
                    break;
                case INSTRUCTION:
                    metricsMap.put(TOTAL_INSTRUCTIONS_COVERED,Pair.of(counter.getCovered(),CodeQualityMetricStatus.Ok));
                    metricsMap.put(TOTAL_INSTRUCTIONS_MISSED, Pair.of(counter.getMissed(),CodeQualityMetricStatus.Ok));
                    break;
                default:
                    // no impl
                    break;
            }
        }
        this.sumMetrics(metricsMap);
        // now add in the missing one
        Map codeQualityMetricMap = quality.getMetrics()
                .stream().collect(Collectors.toMap(CodeQualityMetric::getName, Function.identity()));
        final CodeQualityMetric lineCoverage = codeQualityMetricMap.remove(LINE_COVERAGE);
        quality.getMetrics().remove(lineCoverage);
        quality.addMetric(
                computeCoveragePercent(LINE_COVERAGE,
                        codeQualityMetricMap.get(TOTAL_LINES_COVERED),
                        codeQualityMetricMap.get(TOTAL_LINES_MISSED)));
        final CodeQualityMetric coverage = codeQualityMetricMap.remove(COVERAGE);
        quality.getMetrics().remove(coverage);
        quality.addMetric(
                computeCoveragePercent(COVERAGE,
                        codeQualityMetricMap.get(TOTAL_INSTRUCTIONS_COVERED),
                        codeQualityMetricMap.get(TOTAL_INSTRUCTIONS_MISSED)));


    }

    private CodeQualityMetric computeCoveragePercent(String metricName, CodeQualityMetric covered,CodeQualityMetric missed) {
        double percentageCovered = Double.parseDouble(covered.getValue())*100.0/(Double.parseDouble(covered.getValue()) + Double.parseDouble(missed.getValue()));
        CodeQualityMetric metric = new CodeQualityMetric(metricName);
        metric.setFormattedValue(String.format(Locale.US,"%.3f",percentageCovered));
        metric.setValue(Double.toString(percentageCovered));
        metric.setStatus(CodeQualityMetricStatus.Ok);
        return metric;
    }


    @Override
    public void visit(PmdReport pmdReport) {
        Map> metricsMap = new HashMap<>();
        metricsMap.put(BLOCKER_VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(CRITICAL_VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(MAJOR_VIOLCATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));

        // loop over all the stuff in the report and accumulate violations.
        if (null != pmdReport.getFiles()) {
            pmdReport.getFiles().stream().forEach(violationFile -> {
                violationFile.getViolations().stream().forEach(
                        violation -> {
                            switch (violation.getPriority()) {
                                case 1: {
                                    final Pair metricStatusPair = metricsMap.get(BLOCKER_VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Alert);
                                    metricsMap.put(BLOCKER_VIOLATIONS, newPair);
                                    break;
                                }
                                case 2: {
                                    final Pair metricStatusPair = metricsMap.get(CRITICAL_VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Alert);
                                    metricsMap.put(CRITICAL_VIOLATIONS, newPair);
                                    break;
                                }
                                case 3: {
                                    final Pair metricStatusPair = metricsMap.get(MAJOR_VIOLCATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Warning);
                                    metricsMap.put(MAJOR_VIOLCATIONS, newPair);
                                    break;
                                }
                                default:
                                    final Pair metricStatusPair = metricsMap.get(VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Warning);
                                    metricsMap.put(VIOLATIONS, newPair);
                                    break;
                            }
                        }
                );
            });
        }

        // finally produce the result
        this.sumMetrics(metricsMap);
    }

    @Override
    public void visit(CheckstyleReport checkstyleReport) {
        Map> metricsMap = new HashMap<>();
        metricsMap.put(BLOCKER_VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(CRITICAL_VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(MAJOR_VIOLCATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));
        metricsMap.put(VIOLATIONS, Pair.of(0, CodeQualityMetricStatus.Ok));

        // loop over all the stuff in the report and accumulate violations.
        if (null != checkstyleReport.getFiles()) {
            checkstyleReport.getFiles().stream().forEach(violationFile -> {
                if (null != violationFile.getErrors()) {
                    violationFile.getErrors().stream().forEach(
                        violation -> {
                            switch (violation.getSeverity()) {
                                case error: {
                                    final Pair metricStatusPair = metricsMap.get(BLOCKER_VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Alert);
                                    metricsMap.put(BLOCKER_VIOLATIONS, newPair);
                                    break;
                                }
                                case warning: {
                                    final Pair metricStatusPair = metricsMap.get(CRITICAL_VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Alert);
                                    metricsMap.put(CRITICAL_VIOLATIONS, newPair);
                                    break;
                                }
                                case info: {
                                    final Pair metricStatusPair = metricsMap.get(MAJOR_VIOLCATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Warning);
                                    metricsMap.put(MAJOR_VIOLCATIONS, newPair);
                                    break;
                                }
                                default:
                                    final Pair metricStatusPair = metricsMap.get(VIOLATIONS);
                                    final Pair newPair = Pair.of(metricStatusPair.getLeft().intValue() + 1, CodeQualityMetricStatus.Warning);
                                    metricsMap.put(VIOLATIONS, newPair);
                                    break;
                            }
                        }
                    );
                }
            });
        }

        // finally produce the result
        this.sumMetrics(metricsMap);
    }

    @Override
    public CodeQuality produceResult() {
        return quality;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy