getValue(final Baseline baseline, final Metric metric) {
if (baseline == Baseline.PROJECT) {
return Value.findValue(metric, projectValueMapping);
diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/CoverageStep.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/CoverageStep.java
index cae45e8df..7eddb82b3 100644
--- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/CoverageStep.java
+++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/CoverageStep.java
@@ -10,7 +10,6 @@
import org.apache.commons.lang3.StringUtils;
-import edu.hm.hafner.metric.Node;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -31,7 +30,6 @@
import hudson.model.Item;
import hudson.model.Run;
import hudson.model.TaskListener;
-import hudson.tasks.Recorder;
import hudson.tools.ToolDescriptor;
import hudson.util.ComboBoxModel;
import hudson.util.FormValidation;
@@ -40,21 +38,19 @@
import io.jenkins.plugins.prism.SourceCodeDirectory;
import io.jenkins.plugins.prism.SourceCodeRetention;
import io.jenkins.plugins.util.AbstractExecution;
-import io.jenkins.plugins.util.CharsetValidation;
import io.jenkins.plugins.util.JenkinsFacade;
+import io.jenkins.plugins.util.ValidationUtilities;
/**
- * A pipeline {@code Step} or Freestyle or Maven {@link Recorder} that reads and parses coverage results in a build and
- * adds the results to the persisted build results.
- *
- * Stores the created issues in a {@link Node}. This result is then attached to the {@link Run build} by registering a
- * {@link CoverageBuildAction}.
- *
+ * A pipeline {@code Step} that reads and parses coverage results in a build and adds the results to the persisted build
+ * results. This step only provides the entry point for pipelines, the actual computation is delegated to an associated
+ * Freestyle {@link CoverageRecorder} instance.
*
* @author Ullrich Hafner
*/
public class CoverageStep extends Step implements Serializable {
private static final long serialVersionUID = 34386077204781270L;
+ private static final ValidationUtilities VALIDATION_UTILITIES = new ValidationUtilities();
private List tools = new ArrayList<>();
private List qualityGates = new ArrayList<>();
@@ -126,7 +122,7 @@ public List getQualityGates() {
*/
@DataBoundSetter
public void setId(final String id) {
- new ModelValidation().ensureValidId(id);
+ VALIDATION_UTILITIES.ensureValidId(id);
this.id = id;
}
@@ -296,7 +292,8 @@ static class Execution extends AbstractExecution {
this.step = step;
}
- @Override @CheckForNull
+ @Override
+ @CheckForNull
protected Void run() throws IOException, InterruptedException {
var recorder = new CoverageRecorder();
recorder.setTools(step.getTools());
@@ -324,15 +321,14 @@ protected Void run() throws IOException, InterruptedException {
@SuppressWarnings("unused") // most methods are used by the corresponding jelly view
public static class Descriptor extends StepDescriptor {
private static final JenkinsFacade JENKINS = new JenkinsFacade();
- private static final CharsetValidation CHARSET_VALIDATION = new CharsetValidation();
- private static final ModelValidation MODEL_VALIDATION = new ModelValidation();
@Override
public String getFunctionName() {
return "recordCoverage";
}
- @NonNull @Override
+ @NonNull
+ @Override
public String getDisplayName() {
return Messages.Recorder_Name();
}
@@ -388,7 +384,7 @@ private void add(final ListBoxModel options, final SourceCodeRetention sourceCod
@SuppressWarnings("unused") // used by Stapler view data binding
public ComboBoxModel doFillSourceCodeEncodingItems(@AncestorInPath final AbstractProject, ?> project) {
if (JENKINS.hasPermission(Item.CONFIGURE, project)) {
- return CHARSET_VALIDATION.getAllCharsets();
+ return VALIDATION_UTILITIES.getAllCharsets();
}
return new ComboBoxModel();
}
@@ -411,7 +407,7 @@ public FormValidation doCheckSourceCodeEncoding(@AncestorInPath final AbstractPr
return FormValidation.ok();
}
- return CHARSET_VALIDATION.validateCharset(sourceCodeEncoding);
+ return VALIDATION_UTILITIES.validateCharset(sourceCodeEncoding);
}
/**
@@ -431,7 +427,7 @@ public FormValidation doCheckId(@AncestorInPath final AbstractProject, ?> proj
return FormValidation.ok();
}
- return MODEL_VALIDATION.validateId(id);
+ return VALIDATION_UTILITIES.validateId(id);
}
}
}
diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/CoverageTableModel.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/CoverageTableModel.java
index be9195084..0000e4329 100644
--- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/CoverageTableModel.java
+++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/CoverageTableModel.java
@@ -52,18 +52,6 @@ class CoverageTableModel extends TableModel {
private final RowRenderer renderer;
private final String id;
- /**
- * Creates an indirect coverage changes table model.
- *
- * @param id
- * The ID of the table
- * @param root
- * The root of the coverage tree
- * @param renderer
- * the renderer to use for the file names
- * @param colors
- * The {@link ColorProvider} which provides the used colors
- */
CoverageTableModel(final String id, final Node root, final RowRenderer renderer, final ColorProvider colors) {
super();
@@ -177,7 +165,8 @@ static class CoverageRow {
private final RowRenderer renderer;
private final ColorProvider colorProvider;
- CoverageRow(final FileNode file, final Locale browserLocale, final RowRenderer renderer, final ColorProvider colors) {
+ CoverageRow(final FileNode file, final Locale browserLocale, final RowRenderer renderer,
+ final ColorProvider colors) {
this.file = file;
this.browserLocale = browserLocale;
this.renderer = renderer;
@@ -225,6 +214,7 @@ public int getLoc() {
*
* @param coverage
* the coverage of the element
+ *
* @return the new {@link DetailedCell}
*/
protected DetailedCell> createColoredCoverageColumn(final Coverage coverage) {
@@ -247,6 +237,8 @@ protected DetailedCell> createColoredCoverageColumn(final Coverage coverage) {
/**
* Creates a table cell which colorizes the tendency of the shown coverage delta.
*
+ * @param metric
+ * the metric to use
* @param delta
* The coverage delta as percentage
*
@@ -259,7 +251,7 @@ protected DetailedCell> createColoredCoverageDeltaColumn(final Metric metric,
div().withClasses(COVERAGE_COLUMN_INNER)
.withStyle(String.format("background-color:%s;", colors.getFillColorAsRGBAHex(
TABLE_COVERAGE_COLOR_ALPHA)))
- .withText(FORMATTER.formatDelta(metric, delta, browserLocale)))
+ .withText(FORMATTER.formatDelta(delta, metric, browserLocale)))
.render();
return new DetailedCell<>(cell, percentage);
}
@@ -273,10 +265,9 @@ protected FileNode getFile() {
* {@link Metric}.
*
* @param metric
- * The coverage metric
+ * the coverage metric
*
* @return the created {@link DetailedCell}
- * @since 3.0.0
*/
private DetailedCell> createColoredFileCoverageDeltaColumn(final Metric metric) {
if (file.hasChangeCoverage(metric)) {
diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/ElementFormatter.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/ElementFormatter.java
index 36c599299..97af8c020 100644
--- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/ElementFormatter.java
+++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/ElementFormatter.java
@@ -15,10 +15,6 @@
import hudson.util.ListBoxModel;
-import io.jenkins.plugins.coverage.metrics.visualization.colorization.ColorProvider;
-
-import static io.jenkins.plugins.coverage.metrics.visualization.colorization.ColorProvider.*;
-
/**
* A localized formatter for coverages, metrics, baselines, etc.
*
@@ -36,7 +32,7 @@ public final class ElementFormatter {
* @param value
* the value to format
* @param locale
- * The used locale
+ * the locale to use to render the values
*
* @return the formatted value as plain text
*/
@@ -51,32 +47,11 @@ public String format(final Value value, final Locale locale) {
return String.valueOf(((IntegerValue) value).getValue());
}
if (value instanceof FractionValue) {
- return formatDelta(value.getMetric(), ((FractionValue) value).getFraction(), locale);
+ return formatDelta(((FractionValue) value).getFraction(), value.getMetric(), locale);
}
return value.toString();
}
- public DisplayColors colorize(final Value value, final ColorProvider colorProvider, final Baseline baseline) {
- if (value instanceof Coverage) {
- // FIXME: percentage vs. fraction?
- return getDisplayColors(colorProvider, baseline, ((Coverage) value).getCoveredPercentage());
- }
- if (value instanceof MutationValue) {
- return getDisplayColors(colorProvider, baseline, ((MutationValue) value).getCoveredPercentage());
- }
- if (value instanceof FractionValue) {
- return getDisplayColors(colorProvider, baseline, ((FractionValue) value).getFraction());
- }
- return DEFAULT_COLOR;
-
- }
-
- private static DisplayColors getDisplayColors(final ColorProvider colorProvider, final Baseline baseline,
- final Fraction fraction) {
- var percentage = fraction.doubleValue();
- return baseline.getDisplayColors(percentage * 100.0, colorProvider);
- }
-
/**
* Formats a generic value using a specific rendering method. The type of the given {@link Value} instance is used
* to select the best matching rendering method. This non-object-oriented approach is required since the
@@ -85,7 +60,7 @@ private static DisplayColors getDisplayColors(final ColorProvider colorProvider,
* @param value
* the value to format
* @param locale
- * The used locale
+ * the locale to use to render the values
*
* @return the formatted value as plain text
*/
@@ -122,7 +97,7 @@ private String formatRatio(final int covered, final int total) {
* @param coverage
* the coverage to format
* @param locale
- * The used locale
+ * the locale to use to render the values
*
* @return the formatted percentage as plain text
*/
@@ -140,7 +115,7 @@ public String formatPercentage(final Coverage coverage, final Locale locale) {
* @param fraction
* the fraction to format (in the interval [0, 1])
* @param locale
- * The used locale
+ * the locale to use to render the values
*
* @return the formatted percentage as plain text
*/
@@ -157,7 +132,7 @@ private String formatPercentage(final Fraction fraction, final Locale locale) {
* @param total
* the number of total items
* @param locale
- * The used locale
+ * the locale to use to render the values
*
* @return the formatted percentage as plain text
*/
@@ -169,18 +144,30 @@ public String formatPercentage(final int covered, final int total, final Locale
* Formats a delta percentage to its plain text representation with a leading sign and rounds the value to two
* decimals.
*
+ * @param fraction
+ * the value of the delta
+ * @param metric
+ * the metric of the value
* @param locale
- * The used locale
+ * the locale to use to render the values
*
* @return the formatted delta percentage as plain text with a leading sign
*/
- public String formatDelta(final Metric metric, final Fraction fraction, final Locale locale) {
+ public String formatDelta(final Fraction fraction, final Metric metric, final Locale locale) {
if (metric.equals(Metric.COMPLEXITY) || metric.equals(Metric.LOC)) { // TODO: move to metric?
return String.format(locale, "%+d", fraction.intValue());
}
return String.format(locale, "%+.2f%%", fraction.multiplyBy(HUNDRED).doubleValue());
}
+ /**
+ * Returns a localized human-readable name for the specified metric.
+ *
+ * @param metric
+ * the metric to get the name for
+ *
+ * @return the display name
+ */
public String getDisplayName(final Metric metric) {
switch (metric) {
case CONTAINER:
@@ -214,6 +201,14 @@ public String getDisplayName(final Metric metric) {
}
}
+ /**
+ * Returns a localized human-readable name for the specified baseline.
+ *
+ * @param baseline
+ * the baseline to get the name for
+ *
+ * @return the display name
+ */
public String getDisplayName(final Baseline baseline) {
switch (baseline) {
case PROJECT:
@@ -233,6 +228,11 @@ public String getDisplayName(final Baseline baseline) {
}
}
+ /**
+ * Returns all available metrics as a {@link ListBoxModel}.
+ *
+ * @return the metrics in a {@link ListBoxModel}
+ */
public ListBoxModel getMetricItems() {
ListBoxModel options = new ListBoxModel();
add(options, Metric.MODULE);
@@ -253,6 +253,11 @@ private void add(final ListBoxModel options, final Metric metric) {
options.add(getDisplayName(metric), metric.name());
}
+ /**
+ * Returns all available baselines as a {@link ListBoxModel}.
+ *
+ * @return the baselines in a {@link ListBoxModel}
+ */
public ListBoxModel getBaselineItems() {
ListBoxModel options = new ListBoxModel();
add(options, Baseline.PROJECT);
diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/ModelValidation.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/ModelValidation.java
deleted file mode 100644
index af577090a..000000000
--- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/ModelValidation.java
+++ /dev/null
@@ -1,219 +0,0 @@
-package io.jenkins.plugins.coverage.metrics;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import org.apache.commons.lang3.StringUtils;
-
-import edu.hm.hafner.util.PathUtil;
-import edu.hm.hafner.util.VisibleForTesting;
-import edu.umd.cs.findbugs.annotations.CheckForNull;
-
-import org.kohsuke.stapler.AncestorInPath;
-import org.kohsuke.stapler.QueryParameter;
-import hudson.FilePath;
-import hudson.model.AbstractProject;
-import hudson.util.ComboBoxModel;
-import hudson.util.FormValidation;
-
-import io.jenkins.plugins.util.JenkinsFacade;
-
-/**
- * Validates all properties of a configuration of a static analysis tool in a job.
- *
- * @author Ullrich Hafner
- */
-@SuppressWarnings("PMD.GodClass")
-public class ModelValidation {
- private static final Set ALL_CHARSETS = Charset.availableCharsets().keySet();
- private static final Pattern VALID_ID_PATTERN = Pattern.compile("\\p{Alnum}[\\p{Alnum}-_.]*");
-
- @VisibleForTesting
- static final String NO_REFERENCE_JOB = "-";
-
- private final JenkinsFacade jenkins;
-
- /** Creates a new descriptor. */
- public ModelValidation() {
- this(new JenkinsFacade());
- }
-
- @VisibleForTesting
- ModelValidation(final JenkinsFacade jenkins) {
- super();
-
- this.jenkins = jenkins;
- }
-
- /**
- * Returns all available character set names.
- *
- * @return all available character set names
- * @deprecated moved to Prism API Plugin
- */
- @Deprecated
- public ComboBoxModel getAllCharsets() {
- return new ComboBoxModel(ALL_CHARSETS);
- }
-
- /**
- * Returns the default charset for the specified encoding string. If the default encoding is empty or {@code null},
- * or if the charset is not valid then the default encoding of the platform is returned.
- *
- * @param charset
- * identifier of the character set
- *
- * @return the default charset for the specified encoding string
- * @deprecated moved to Prism API Plugin
- */
- @Deprecated
- public Charset getCharset(@CheckForNull final String charset) {
- try {
- if (StringUtils.isNotBlank(charset)) {
- return Charset.forName(charset);
- }
- }
- catch (UnsupportedCharsetException | IllegalCharsetNameException exception) {
- // ignore and return default
- }
- return Charset.defaultCharset();
- }
-
- /**
- * Ensures that the specified ID is valid.
- *
- * @param id
- * the custom ID of the tool
- *
- * @throws IllegalArgumentException
- * if the ID is not valid
- */
- public void ensureValidId(final String id) {
- if (!isValidId(id)) {
- throw new IllegalArgumentException("INVALID ID TODO");
- }
- }
-
- /**
- * Performs on-the-fly validation of the ID.
- *
- * @param id
- * the custom ID of the tool
- *
- * @return the validation result
- */
- public FormValidation validateId(final String id) {
- if (isValidId(id)) {
- return FormValidation.ok();
- }
- return FormValidation.error("FIXME ERROR");
- }
-
- private boolean isValidId(final String id) {
- return StringUtils.isEmpty(id) || VALID_ID_PATTERN.matcher(id).matches();
- }
-
- /**
- * Performs on-the-fly validation of the character encoding.
- *
- * @param reportEncoding
- * the character encoding
- *
- * @return the validation result
- * @deprecated moved to Prism API Plugin
- */
- @Deprecated
- public FormValidation validateCharset(final String reportEncoding) {
- try {
- if (StringUtils.isBlank(reportEncoding) || Charset.isSupported(reportEncoding)) {
- return FormValidation.ok();
- }
- }
- catch (IllegalCharsetNameException | UnsupportedCharsetException ignore) {
- // throw a FormValidation error
- }
- return FormValidation.errorWithMarkup(createWrongEncodingErrorMessage());
- }
-
- @VisibleForTesting
- static String createWrongEncodingErrorMessage() {
- return "FIXME";
- }
-
- /**
- * Performs on-the-fly validation on the ant pattern for input files.
- *
- * @param project
- * the project that is configured
- * @param pattern
- * the file pattern
- *
- * @return the validation result
- */
- public FormValidation doCheckPattern(final AbstractProject, ?> project, final String pattern) {
- if (project != null) { // there is no workspace in pipelines
- try {
- FilePath workspace = project.getSomeWorkspace();
- if (workspace != null && workspace.exists()) {
- return validatePatternInWorkspace(pattern, workspace);
- }
- }
- catch (InterruptedException | IOException ignore) {
- // ignore and return ok
- }
- }
-
- return FormValidation.ok();
- }
-
- private FormValidation validatePatternInWorkspace(final String pattern, final FilePath workspace)
- throws IOException, InterruptedException {
- String result = workspace.validateAntFileMask(pattern, FilePath.VALIDATE_ANT_FILE_MASK_BOUND);
- if (result != null) {
- return FormValidation.error(result);
- }
- return FormValidation.ok();
- }
-
- /**
- * Performs on-the-fly validation on the source code directory.
- *
- * @param project
- * the project that is configured
- * @param sourceDirectory
- * the file pattern
- *
- * @return the validation result
- * @deprecated moved to Prism API Plugin
- */
- @Deprecated
- public FormValidation doCheckSourceDirectory(@AncestorInPath final AbstractProject, ?> project,
- @QueryParameter final String sourceDirectory) {
- if (project != null) { // there is no workspace in pipelines
- try {
- FilePath workspace = project.getSomeWorkspace();
- if (workspace != null && workspace.exists()) {
- return validateRelativePath(sourceDirectory, workspace);
- }
- }
- catch (InterruptedException | IOException ignore) {
- // ignore and return ok
- }
- }
-
- return FormValidation.ok();
- }
-
- private FormValidation validateRelativePath(
- @QueryParameter final String sourceDirectory, final FilePath workspace) throws IOException {
- PathUtil pathUtil = new PathUtil();
- if (pathUtil.isAbsolute(sourceDirectory)) {
- return FormValidation.ok();
- }
- return workspace.validateRelativeDirectory(sourceDirectory);
- }
-}