getAvailableCoverageMetrics() {
- return Arrays.asList(LINE, BRANCH, INSTRUCTION, METHOD, CLASS, FILE, PACKAGE, MODULE);
- }
-
- /**
- * Checks if this instance has a name that is equal to the specified name (ignoring case).
- *
- * @param searchName
- * the coverage metric name to check
- *
- * @return {@code true} if this instance has the same name, {@code false} otherwise
- */
- public boolean equalsIgnoreCase(final String searchName) {
- return equalsIgnoreCase(getName(), searchName);
- }
-
- /**
- * Compares two CharSequences, returning {@code true} if they represent
- * equal sequences of characters, ignoring case.
- *
- * {@code null}s are handled without exceptions. Two {@code null}
- * references are considered equal. The comparison is case insensitive.
- *
- *
- * StringUtils.equalsIgnoreCase(null, null) = true
- * StringUtils.equalsIgnoreCase(null, "abc") = false
- * StringUtils.equalsIgnoreCase("abc", null) = false
- * StringUtils.equalsIgnoreCase("abc", "abc") = true
- * StringUtils.equalsIgnoreCase("abc", "ABC") = true
- *
- *
- * @param a
- * the first CharSequence, may be {@code null}
- * @param b
- * the second CharSequence, may be {@code null}
- *
- * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}
- */
- public static boolean equalsIgnoreCase(@CheckForNull final String a, @CheckForNull final String b) {
- return StringUtils.equals(normalize(a), normalize(b));
- }
-
- private static String normalize(@CheckForNull final String input) {
- return StringUtils.defaultString(input).toUpperCase(Locale.ENGLISH);
- }
-
- private final String name;
- private final int order;
- private final boolean leaf;
-
- private CoverageMetric(final String name, final int order) {
- this(name, order, MetricType.COMPOSITE);
- }
-
- private CoverageMetric(final String name, final int order, final MetricType type) {
- this.name = name;
- this.order = order;
- this.leaf = type == MetricType.LEAF;
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isLeaf() {
- return leaf;
- }
-
- @Override
- public String toString() {
- return name;
- }
-
- @Override
- public int compareTo(final CoverageMetric other) {
- return order - other.order;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- CoverageMetric that = (CoverageMetric) o;
-
- return name.equals(that.name);
- }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
-}
diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/model/CoverageNode.java b/plugin/src/main/java/io/jenkins/plugins/coverage/model/CoverageNode.java
deleted file mode 100644
index dde12a63e..000000000
--- a/plugin/src/main/java/io/jenkins/plugins/coverage/model/CoverageNode.java
+++ /dev/null
@@ -1,780 +0,0 @@
-package io.jenkins.plugins.coverage.model;
-
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Deque;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.math.Fraction;
-
-import edu.hm.hafner.util.Ensure;
-import edu.hm.hafner.util.VisibleForTesting;
-import edu.umd.cs.findbugs.annotations.CheckForNull;
-
-import one.util.streamex.StreamEx;
-
-import io.jenkins.plugins.coverage.model.Coverage.CoverageBuilder;
-
-/**
- * A hierarchical decomposition of coverage results.
- *
- * @author Ullrich Hafner
- */
-@SuppressWarnings({"PMD.GodClass", "PMD.CyclomaticComplexity"})
-public class CoverageNode implements Serializable {
- private static final long serialVersionUID = -6608885640271135273L;
-
- private static final Coverage COVERED_NODE = new Coverage.CoverageBuilder().setCovered(1).setMissed(0).build();
- private static final Coverage MISSED_NODE = new Coverage.CoverageBuilder().setCovered(0).setMissed(1).build();
-
- /** Transient non static {@link CoverageTreeCreator} in order to be able to mock it for tests. */
- private transient CoverageTreeCreator coverageTreeCreator;
-
- static final String ROOT = "^";
-
- private final CoverageMetric metric;
- private final String name;
- private final List children = new ArrayList<>();
- private final List leaves = new ArrayList<>();
- @CheckForNull
- private CoverageNode parent;
-
- /**
- * Creates a new coverage item node with the given name.
- *
- * @param metric
- * the coverage metric this node belongs to
- * @param name
- * the human-readable name of the node
- */
- public CoverageNode(final CoverageMetric metric, final String name) {
- this(metric, name, new CoverageTreeCreator());
- }
-
- /**
- * Creates a new coverage item node with the given name and a mocked {@link CoverageTreeCreator}.
- *
- * @param metric
- * the coverage metric this node belongs to
- * @param name
- * the human-readable name of the node
- * @param coverageTreeCreator
- * the coverage tree creator
- */
- @VisibleForTesting
- public CoverageNode(final CoverageMetric metric, final String name, final CoverageTreeCreator coverageTreeCreator) {
- this.metric = metric;
- this.name = name;
- this.coverageTreeCreator = coverageTreeCreator;
- }
-
- /**
- * Called after de-serialization to restore transient fields.
- *
- * @return this
- * @throws ObjectStreamException
- * if the operation failed
- */
- protected Object readResolve() throws ObjectStreamException {
- if (coverageTreeCreator == null) {
- coverageTreeCreator = new CoverageTreeCreator();
- }
- return this;
- }
-
- /**
- * Gets the parent node.
- *
- * @return the parent, if existent
- * @throws IllegalStateException
- * if no parent exists
- */
- public CoverageNode getParent() {
- if (parent == null) {
- throw new IllegalStateException("Parent is not set");
- }
- return parent;
- }
-
- /**
- * Returns the source code path of this node.
- *
- * @return the element type
- */
- public String getPath() {
- return StringUtils.EMPTY;
- }
-
- protected String mergePath(final String localPath) {
- // default packages are named '-'
- if ("-".equals(localPath)) {
- return StringUtils.EMPTY;
- }
-
- if (hasParent()) {
- String parentPath = getParent().getPath();
-
- if (StringUtils.isBlank(parentPath)) {
- return localPath;
- }
- if (StringUtils.isBlank(localPath)) {
- return parentPath;
- }
- return parentPath + "/" + localPath;
- }
-
- return localPath;
- }
-
- /**
- * Returns the type if the coverage metric for this node.
- *
- * @return the element type
- */
- public CoverageMetric getMetric() {
- return metric;
- }
-
- /**
- * Returns the available coverage metrics for the whole tree starting with this node.
- *
- * @return the elements in this tree
- */
- public SortedSet getMetrics() {
- SortedSet elements = children.stream()
- .map(CoverageNode::getMetrics)
- .flatMap(Collection::stream)
- .collect(Collectors.toCollection(TreeSet::new));
-
- elements.add(getMetric());
- leaves.stream().map(CoverageLeaf::getMetric).forEach(elements::add);
-
- return elements;
- }
-
- /**
- * Returns the most important coverage metrics.
- *
- * @return most important coverage metrics
- */
- public Collection getImportantMetrics() {
- List importantElements = new ArrayList<>();
- importantElements.add(CoverageMetric.LINE);
- importantElements.add(CoverageMetric.BRANCH);
- importantElements.retainAll(getMetrics());
- return importantElements;
- }
-
- /**
- * Returns a mapping of metric to coverage. The root of the tree will be skipped.
- *
- * @return a mapping of metric to coverage.
- */
- public SortedMap getMetricsDistribution() {
- return getMetrics().stream()
- .collect(Collectors.toMap(Function.identity(), this::getCoverage, (o1, o2) -> o1, TreeMap::new));
- }
-
- /**
- * Gets the coverage for each available metric as a fraction between 0 and 1.
- *
- * @return the coverage fractions mapped by their metric
- */
- public SortedMap getMetricFractions() {
- if (children.isEmpty() && leaves.isEmpty()) {
- // prevents returning a module coverage of 0% if the tree has no leaves since the coverage is not existent
- return new TreeMap<>();
- }
- return getMetrics().stream()
- .collect(Collectors.toMap(Function.identity(),
- searchMetric -> getCoverage(searchMetric).getCoveredFraction(), (o1, o2) -> o1,
- TreeMap::new));
- }
-
- /**
- * Gets the coverage for each available metric as a percentage between 0 and 100.
- *
- * @return the coverage percentages mapped by their metric
- */
- public SortedMap getMetricPercentages() {
- return StreamEx.of(getMetricFractions().entrySet())
- .toSortedMap(Entry::getKey, e -> CoveragePercentage.valueOf(e.getValue()));
- }
-
- public String getName() {
- return name;
- }
-
- public List getChildren() {
- return children;
- }
-
- public List getLeaves() {
- return leaves;
- }
-
- private void addAll(final List nodes) {
- nodes.forEach(this::add);
- }
-
- /**
- * Appends the specified child element to the list of children.
- *
- * @param child
- * the child to add
- */
- public void add(final CoverageNode child) {
- children.add(child);
- child.setParent(this);
- }
-
- /**
- * Appends the specified leaf element to the list of leaves.
- *
- * @param leaf
- * the leaf to add
- */
- public void add(final CoverageLeaf leaf) {
- leaves.add(leaf);
- }
-
- /**
- * Removes this node from the coverage tree.
- */
- void remove() {
- // TODO: remove this method when unique paths are handled correctly
- if (hasParent()) {
- getParent().children.remove(this);
- clearEmptyPaths(getParent());
- }
- }
-
- /**
- * Clears an empty tree path from the bottom of the tree to the top, beginning with the passed node.
- *
- * @param node The {@link CoverageNode node} to begin from
- */
- private void clearEmptyPaths(final CoverageNode node) {
- // TODO: remove this method when unique paths are handled correctly
- if (node != null && node.getChildren().isEmpty()) {
- node.remove();
- }
- }
-
- /**
- * Returns whether this node is the root of the tree.
- *
- * @return {@code true} if this node is the root of the tree, {@code false} otherwise
- */
- public boolean isRoot() {
- return parent == null;
- }
-
- /**
- * Returns whether this node has a parent node.
- *
- * @return {@code true} if this node has a parent node, {@code false} if it is the root of the hierarchy
- */
- public boolean hasParent() {
- return !isRoot();
- }
-
- void setParent(final CoverageNode parent) {
- this.parent = Objects.requireNonNull(parent);
- }
-
- /**
- * Returns the name of the parent element or "-" if there is no such element.
- *
- * @return the name of the parent element
- */
- public String getParentName() {
- if (parent == null) {
- return ROOT;
- }
- CoverageMetric type = parent.getMetric();
-
- List parentsOfSameType = new ArrayList<>();
- for (CoverageNode node = parent; node != null && node.getMetric().equals(type); node = node.parent) {
- parentsOfSameType.add(0, node.getName());
- }
- return String.join(".", parentsOfSameType);
- }
-
- /**
- * Prints the coverage for the specified element. Uses {@code Locale.getDefault()} to format the percentage.
- *
- * @param searchMetric
- * the element to print the coverage for
- *
- * @return coverage ratio in a human-readable format
- * @see #printCoverageFor(CoverageMetric, Locale)
- */
- public String printCoverageFor(final CoverageMetric searchMetric) {
- return printCoverageFor(searchMetric, Locale.getDefault());
- }
-
- /**
- * Prints the coverage for the specified element.
- *
- * @param searchMetric
- * the element to print the coverage for
- * @param locale
- * the locale to use when formatting the percentage
- *
- * @return coverage ratio in a human-readable format
- */
- public String printCoverageFor(final CoverageMetric searchMetric, final Locale locale) {
- return getCoverage(searchMetric).formatCoveredPercentage(locale);
- }
-
- /**
- * Returns the coverage for the specified metric.
- *
- * @param searchMetric
- * the element to get the coverage for
- *
- * @return coverage ratio
- */
- public Coverage getCoverage(final CoverageMetric searchMetric) {
- if (searchMetric.isLeaf()) {
- Coverage childrenCoverage = children.stream()
- .map(node -> node.getCoverage(searchMetric))
- .reduce(CoverageBuilder.NO_COVERAGE, Coverage::add);
- return leaves.stream()
- .map(node -> node.getCoverage(searchMetric))
- .reduce(childrenCoverage, Coverage::add);
- }
- else {
- Coverage childrenCoverage = children.stream()
- .map(node -> node.getCoverage(searchMetric))
- .reduce(CoverageBuilder.NO_COVERAGE, Coverage::add);
-
- if (metric.equals(searchMetric)) {
- if (getCoverage(CoverageMetric.LINE).getCovered() > 0) {
- return childrenCoverage.add(COVERED_NODE);
- }
- else {
- return childrenCoverage.add(MISSED_NODE);
- }
- }
- return childrenCoverage;
- }
- }
-
- /**
- * Computes the coverage delta between this node and the specified reference node as fractions between 0 and 1.
- *
- * @param reference
- * the reference node
- *
- * @return the delta coverage for each available metric as fraction
- */
- public SortedMap computeDelta(final CoverageNode reference) {
- SortedMap deltaPercentages = new TreeMap<>();
- SortedMap metricPercentages = getMetricFractions();
- SortedMap referencePercentages = reference.getMetricFractions();
- metricPercentages.forEach((key, value) ->
- deltaPercentages.put(key,
- new SafeFraction(value).subtract(referencePercentages.getOrDefault(key, Fraction.ZERO))));
- return deltaPercentages;
- }
-
- /**
- * Computes the coverage delta between this node and the specified reference node as percentage between 0 and 100.
- *
- * @param reference
- * the reference node
- *
- * @return the delta coverage for each available metric as percentage
- */
- public SortedMap