This is an automated email from the ASF dual-hosted git repository.
michaelo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-invoker-plugin.git
The following commit(s) were added to refs/heads/master by this push:
new a154e5b [MINVOKER-344] Move reporting rendering logic into a
ReportRenderer class
a154e5b is described below
commit a154e5b13dd7d900829d1d951efff50c41f25738
Author: Michael Osipov <[email protected]>
AuthorDate: Sun Jun 11 16:07:27 2023 +0200
[MINVOKER-344] Move reporting rendering logic into a ReportRenderer class
This closes #193
---
.../maven/plugins/invoker/InvokerReport.java | 254 ++-------------------
.../plugins/invoker/InvokerReportRenderer.java | 210 +++++++++++++++++
src/main/resources/invoker-report.properties | 37 ++-
src/main/resources/invoker-report_de.properties | 33 ++-
src/main/resources/invoker-report_fr.properties | 35 ++-
5 files changed, 281 insertions(+), 288 deletions(-)
diff --git a/src/main/java/org/apache/maven/plugins/invoker/InvokerReport.java
b/src/main/java/org/apache/maven/plugins/invoker/InvokerReport.java
index 40cc33b..339705a 100644
--- a/src/main/java/org/apache/maven/plugins/invoker/InvokerReport.java
+++ b/src/main/java/org/apache/maven/plugins/invoker/InvokerReport.java
@@ -20,15 +20,10 @@ package org.apache.maven.plugins.invoker;
import java.io.File;
import java.io.IOException;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.MessageFormat;
-import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
-import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
@@ -52,12 +47,6 @@ import
org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@Mojo(name = "report", threadSafe = true)
public class InvokerReport extends AbstractMavenReport {
- /**
- * Internationalization component.
- */
- @Component
- protected I18N i18n;
-
/**
* Base directory where all build reports have been written to.
*/
@@ -65,58 +54,14 @@ public class InvokerReport extends AbstractMavenReport {
private File reportsDirectory;
/**
- * The number format used to print percent values in the report locale.
- */
- private NumberFormat percentFormat;
-
- /**
- * The number format used to print time values in the report locale.
- */
- private NumberFormat secondsFormat;
-
- /**
- * The format used to print build name and description.
+ * Internationalization component
*/
- private MessageFormat nameAndDescriptionFormat;
+ @Component
+ protected I18N i18n;
protected void executeReport(Locale locale) throws MavenReportException {
- DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
- percentFormat = new DecimalFormat(getText(locale,
"report.invoker.format.percent"), symbols);
- secondsFormat = new DecimalFormat(getText(locale,
"report.invoker.format.seconds"), symbols);
- nameAndDescriptionFormat = new MessageFormat(getText(locale,
"report.invoker.format.name_with_description"));
-
- Sink sink = getSink();
-
- sink.head();
-
- sink.title();
- sink.text(getText(locale, "report.invoker.result.title"));
- sink.title_();
-
- sink.head_();
-
- sink.body();
-
- sink.section1();
- sink.sectionTitle1();
- sink.text(getText(locale, "report.invoker.result.title"));
- sink.sectionTitle1_();
- sink.paragraph();
- sink.text(getText(locale, "report.invoker.result.description"));
- sink.paragraph_();
- sink.section1_();
-
- // ----------------------------------
- // build buildJob beans
- // ----------------------------------
- File[] reportFiles = ReportUtils.getReportFiles(reportsDirectory);
- if (reportFiles.length <= 0) {
- getLog().info("no invoker report files found, skip report
generation");
- return;
- }
-
+ File[] reportFiles = getReportFiles();
BuildJobXpp3Reader buildJobReader = new BuildJobXpp3Reader();
-
List<BuildJob> buildJobs = new ArrayList<>(reportFiles.length);
for (File reportFile : reportFiles) {
try (XmlStreamReader xmlReader =
ReaderFactory.newXmlReader(reportFile)) {
@@ -127,193 +72,38 @@ public class InvokerReport extends AbstractMavenReport {
throw new MavenReportException("Failed to read report file: "
+ reportFile, e);
}
}
-
- // ----------------------------------
- // summary
- // ----------------------------------
-
- constructSummarySection(buildJobs, locale);
-
- // ----------------------------------
- // per file/it detail
- // ----------------------------------
-
- sink.section2();
- sink.sectionTitle2();
-
- sink.text(getText(locale, "report.invoker.detail.title"));
-
- sink.sectionTitle2_();
-
- sink.section2_();
-
- // detail tests table header
- sink.table();
- sink.tableRows(null, false);
-
- sink.tableRow();
- // -------------------------------------------
- // name | Result | time | message
- // -------------------------------------------
- sinkTableHeader(sink, getText(locale, "report.invoker.detail.name"));
- sinkTableHeader(sink, getText(locale, "report.invoker.detail.result"));
- sinkTableHeader(sink, getText(locale, "report.invoker.detail.time"));
- sinkTableHeader(sink, getText(locale,
"report.invoker.detail.message"));
-
- sink.tableRow_();
-
- for (BuildJob buildJob : buildJobs) {
- renderBuildJob(buildJob);
- }
-
- sink.tableRows_();
- sink.table_();
-
- sink.body_();
-
- sink.flush();
- sink.close();
+ InvokerReportRenderer r = new InvokerReportRenderer(getSink(), i18n,
locale, getLog(), buildJobs);
+ r.render();
}
- private void constructSummarySection(List<? extends BuildJob> buildJobs,
Locale locale) {
- Sink sink = getSink();
-
- sink.section2();
- sink.sectionTitle2();
-
- sink.text(getText(locale, "report.invoker.summary.title"));
-
- sink.sectionTitle2_();
- sink.section2_();
-
- //
------------------------------------------------------------------------
- // Building a table with
- // it number | succes nb | failed nb | Success rate | total time | avg
time
- //
------------------------------------------------------------------------
-
- sink.table();
- sink.tableRows(null, false);
-
- sink.tableRow();
-
- sinkTableHeader(sink, getText(locale,
"report.invoker.summary.number"));
- sinkTableHeader(sink, getText(locale,
"report.invoker.summary.success"));
- sinkTableHeader(sink, getText(locale,
"report.invoker.summary.failed"));
- sinkTableHeader(sink, getText(locale,
"report.invoker.summary.skipped"));
- sinkTableHeader(sink, getText(locale,
"report.invoker.summary.success.rate"));
- sinkTableHeader(sink, getText(locale,
"report.invoker.summary.time.total"));
- sinkTableHeader(sink, getText(locale,
"report.invoker.summary.time.avg"));
-
- int number = buildJobs.size();
- int success = 0;
- int failed = 0;
- int skipped = 0;
- double totalTime = 0;
-
- for (BuildJob buildJob : buildJobs) {
- if (BuildJob.Result.SUCCESS.equals(buildJob.getResult())) {
- success++;
- } else if (BuildJob.Result.SKIPPED.equals(buildJob.getResult())) {
- skipped++;
- } else {
- failed++;
- }
- totalTime += buildJob.getTime();
- }
-
- sink.tableRow_();
- sink.tableRow();
-
- sinkCell(sink, Integer.toString(number));
- sinkCell(sink, Integer.toString(success));
- sinkCell(sink, Integer.toString(failed));
- sinkCell(sink, Integer.toString(skipped));
-
- if (success + failed > 0) {
- sinkCell(sink, percentFormat.format((double) success / (success +
failed)));
- } else {
- sinkCell(sink, "");
- }
-
- sinkCell(sink, secondsFormat.format(totalTime));
-
- sinkCell(sink, secondsFormat.format(totalTime / number));
-
- sink.tableRow_();
-
- sink.tableRows_();
- sink.table_();
- }
-
- private void renderBuildJob(BuildJob buildJob) {
- Sink sink = getSink();
- sink.tableRow();
- sinkCell(sink, getBuildJobReportName(buildJob));
- // FIXME image
- sinkCell(sink, buildJob.getResult());
- sinkCell(sink, secondsFormat.format(buildJob.getTime()));
- sinkCell(sink, buildJob.getFailureMessage());
- sink.tableRow_();
- }
-
- private String getBuildJobReportName(BuildJob buildJob) {
- String buildJobName = buildJob.getName();
- String buildJobDescription = buildJob.getDescription();
- boolean emptyJobName = buildJobName == null || buildJobName.isEmpty();
- boolean emptyJobDescription = buildJobDescription == null ||
buildJobDescription.isEmpty();
- boolean isReportJobNameComplete = !emptyJobName &&
!emptyJobDescription;
- if (isReportJobNameComplete) {
- return getFormattedName(buildJobName, buildJobDescription);
- } else {
- String buildJobProject = buildJob.getProject();
- if (!emptyJobName) {
- getLog().warn(incompleteNameWarning("description",
buildJobProject));
- } else if (!emptyJobDescription) {
- getLog().warn(incompleteNameWarning("name", buildJobProject));
- }
- return buildJobProject;
- }
- }
-
- private static String incompleteNameWarning(String missing, String pom) {
- return String.format(
- "Incomplete job name-description: %s is missing. " + "POM (%s)
will be used in place of job name.",
- missing, pom);
+ /**
+ * @param locale The locale
+ * @param key The key to search for
+ * @return The text appropriate for the locale.
+ */
+ private String getI18nString(Locale locale, String key) {
+ return i18n.getString("invoker-report", locale, "report.invoker." +
key);
}
- private String getFormattedName(String name, String description) {
- return nameAndDescriptionFormat.format(new Object[] {name,
description});
+ /** {@inheritDoc} */
+ public String getName(Locale locale) {
+ return getI18nString(locale, "name");
}
+ /** {@inheritDoc} */
public String getDescription(Locale locale) {
- return getText(locale, "report.invoker.result.description");
- }
-
- public String getName(Locale locale) {
- return getText(locale, "report.invoker.result.name");
+ return getI18nString(locale, "description");
}
public String getOutputName() {
return "invoker-report";
}
- public boolean canGenerateReport() {
- return ReportUtils.getReportFiles(reportsDirectory).length > 0;
+ private File[] getReportFiles() {
+ return ReportUtils.getReportFiles(reportsDirectory);
}
- private String getText(Locale locale, String key) {
- return i18n.getString("invoker-report", locale, key);
- }
-
- private void sinkTableHeader(Sink sink, String header) {
- sink.tableHeaderCell();
- sink.text(header);
- sink.tableHeaderCell_();
- }
-
- private void sinkCell(Sink sink, String text) {
- sink.tableCell();
- sink.text(text);
- sink.tableCell_();
+ public boolean canGenerateReport() {
+ return getReportFiles().length > 0;
}
}
diff --git
a/src/main/java/org/apache/maven/plugins/invoker/InvokerReportRenderer.java
b/src/main/java/org/apache/maven/plugins/invoker/InvokerReportRenderer.java
new file mode 100644
index 0000000..eae9739
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/invoker/InvokerReportRenderer.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugins.invoker;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.maven.doxia.sink.Sink;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugins.invoker.model.BuildJob;
+import org.apache.maven.reporting.AbstractMavenReportRenderer;
+import org.codehaus.plexus.i18n.I18N;
+
+public class InvokerReportRenderer extends AbstractMavenReportRenderer {
+ private final I18N i18n;
+ private final Locale locale;
+ private final Log log;
+ private final List<BuildJob> buildJobs;
+
+ /**
+ * The number format used to print percent values in the report locale.
+ */
+ private NumberFormat percentFormat;
+
+ /**
+ * The number format used to print time values in the report locale.
+ */
+ private NumberFormat secondsFormat;
+
+ /**
+ * The format used to print build name and description.
+ */
+ private MessageFormat nameAndDescriptionFormat;
+
+ public InvokerReportRenderer(Sink sink, I18N i18n, Locale locale, Log log,
List<BuildJob> buildJobs) {
+ super(sink);
+ this.i18n = i18n;
+ this.locale = locale;
+ this.log = log;
+ this.buildJobs = buildJobs;
+ }
+
+ @Override
+ public String getTitle() {
+ return getI18nString("title");
+ }
+
+ /**
+ * @param key The key to translate.
+ * @return the translated key.
+ */
+ private String getI18nString(String key) {
+ return i18n.getString("invoker-report", locale, "report.invoker." +
key);
+ }
+
+ /**
+ * @param key The key to translate.
+ * @param args The args to pass to translated string.
+ * @return the translated key.
+ */
+ private String formatI18nString(String key, Object... args) {
+ return i18n.format("invoker-report", locale, "report.invoker." + key,
args);
+ }
+
+ @Override
+ protected void renderBody() {
+ DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
+ percentFormat = new DecimalFormat(getI18nString("format.percent"),
symbols);
+ secondsFormat = new DecimalFormat(getI18nString("format.seconds"),
symbols);
+ nameAndDescriptionFormat = new
MessageFormat(getI18nString("format.name_with_description"));
+
+ startSection(getTitle());
+ paragraph(getI18nString("description"));
+
+ renderSectionSummary();
+
+ renderSectionDetails();
+
+ endSection();
+ }
+
+ private void renderSectionSummary() {
+ startSection(getI18nString("summary.title"));
+
+ startTable();
+
+ tableHeader(new String[] {
+ getI18nString("summary.builds"),
+ getI18nString("summary.success"),
+ getI18nString("summary.failures"),
+ getI18nString("summary.skipped"),
+ getI18nString("summary.successrate"),
+ getI18nString("summary.time")
+ });
+
+ int totalBuilds = buildJobs.size();
+ int totalSuccess = 0;
+ int totalFailures = 0;
+ int totalSkipped = 0;
+ float totalTime = 0.0f;
+
+ for (BuildJob buildJob : buildJobs) {
+ switch (buildJob.getResult()) {
+ case BuildJob.Result.SUCCESS:
+ totalSuccess++;
+ break;
+ case BuildJob.Result.SKIPPED:
+ totalSkipped++;
+ break;
+ default:
+ totalFailures++;
+ }
+ totalTime += buildJob.getTime();
+ }
+
+ tableRow(new String[] {
+ Integer.toString(totalBuilds),
+ Integer.toString(totalSuccess),
+ Integer.toString(totalFailures),
+ Integer.toString(totalSkipped),
+ (totalSuccess + totalFailures > 0)
+ ? percentFormat.format(totalSuccess / (float)
(totalSuccess + totalFailures))
+ : "",
+ secondsFormat.format(totalTime)
+ });
+
+ endTable();
+
+ endSection();
+ }
+
+ private void renderSectionDetails() {
+ startSection(getI18nString("detail.title"));
+
+ startTable();
+
+ tableHeader(new String[] {
+ getI18nString("detail.name"),
+ getI18nString("detail.result"),
+ getI18nString("detail.time"),
+ getI18nString("detail.message")
+ });
+
+ for (BuildJob buildJob : buildJobs) {
+ renderBuildJob(buildJob);
+ }
+
+ endTable();
+
+ endSection();
+ }
+
+ private void renderBuildJob(BuildJob buildJob) {
+ tableRow(new String[] {
+ getBuildJobReportName(buildJob),
+ // FIXME image
+ buildJob.getResult(),
+ secondsFormat.format(buildJob.getTime()),
+ buildJob.getFailureMessage()
+ });
+ }
+
+ private String getBuildJobReportName(BuildJob buildJob) {
+ String buildJobName = buildJob.getName();
+ String buildJobDescription = buildJob.getDescription();
+ boolean emptyJobName = buildJobName == null || buildJobName.isEmpty();
+ boolean emptyJobDescription = buildJobDescription == null ||
buildJobDescription.isEmpty();
+ boolean isReportJobNameComplete = !emptyJobName &&
!emptyJobDescription;
+ if (isReportJobNameComplete) {
+ return getFormattedName(buildJobName, buildJobDescription);
+ } else {
+ String buildJobProject = buildJob.getProject();
+ if (!emptyJobName) {
+ log.warn(incompleteNameWarning("description",
buildJobProject));
+ } else if (!emptyJobDescription) {
+ log.warn(incompleteNameWarning("name", buildJobProject));
+ }
+ return buildJobProject;
+ }
+ }
+
+ private static String incompleteNameWarning(String missing, String pom) {
+ return "Incomplete job name-description: " + missing + " is missing.
POM (" + pom
+ + ") will be used in place of job name!";
+ }
+
+ private String getFormattedName(String name, String description) {
+ return nameAndDescriptionFormat.format(new Object[] {name,
description});
+ }
+}
diff --git a/src/main/resources/invoker-report.properties
b/src/main/resources/invoker-report.properties
index 5fe569d..e746c3e 100644
--- a/src/main/resources/invoker-report.properties
+++ b/src/main/resources/invoker-report.properties
@@ -15,22 +15,21 @@
# specific language governing permissions and limitations
# under the License.
-report.invoker.result.description = The results of the Maven invocations.
-report.invoker.result.name = Invoker Build Results
-report.invoker.result.title = Invoker Report
-report.invoker.summary.title = Summary
-report.invoker.summary.number = Builds
-report.invoker.summary.success = Success
-report.invoker.summary.failed = Failures
-report.invoker.summary.skipped = Skipped
-report.invoker.summary.success.rate = Success Rate
-report.invoker.summary.time.total = Total Time
-report.invoker.summary.time.avg = Avg Time
-report.invoker.detail.title = Build Details
-report.invoker.detail.name = Name
-report.invoker.detail.result = Result
-report.invoker.detail.time = Time
-report.invoker.detail.message = Message
-report.invoker.format.percent = 0.0%
-report.invoker.format.seconds = 0.0\u00A0s
-report.invoker.format.name_with_description = {0}: {1}
+report.invoker.name=Invoker
+report.invoker.description=Report on the build results of the Maven
invocations.
+report.invoker.title=Invoker Report
+report.invoker.summary.title=Summary
+report.invoker.summary.builds=Builds
+report.invoker.summary.success=Success
+report.invoker.summary.failures=Failures
+report.invoker.summary.skipped=Skipped
+report.invoker.summary.successrate=Success Rate
+report.invoker.summary.time=Time
+report.invoker.detail.title=Build Details
+report.invoker.detail.name=Name
+report.invoker.detail.result=Result
+report.invoker.detail.time=Time
+report.invoker.detail.message=Message
+report.invoker.format.percent=0.0%
+report.invoker.format.seconds=0.0\u00A0s
+report.invoker.format.name_with_description={0}: {1}
diff --git a/src/main/resources/invoker-report_de.properties
b/src/main/resources/invoker-report_de.properties
index d1016e3..41e030b 100644
--- a/src/main/resources/invoker-report_de.properties
+++ b/src/main/resources/invoker-report_de.properties
@@ -15,21 +15,18 @@
# specific language governing permissions and limitations
# under the License.
-report.invoker.result.description = Die Ergebnisse der
Maven-Ausf\u00FChrungen.
-report.invoker.result.name = Invoker-Build-Ergebnisse
-report.invoker.result.title = Invoker-Bericht
-report.invoker.summary.title = Zusammenfassungen
-report.invoker.summary.number = Builds
-report.invoker.summary.success = Erfolge
-report.invoker.summary.failed = Fehlschl\u00E4ge
-report.invoker.summary.skipped = Ausgelassen
-report.invoker.summary.success.rate = Erfolgsrate
-report.invoker.summary.time.total = Gesamtzeit
-report.invoker.summary.time.avg = Durchschnittszeit
-report.invoker.detail.title = Build-Details
-report.invoker.detail.name = Name
-report.invoker.detail.result = Ergebnis
-report.invoker.detail.time = Zeit
-report.invoker.detail.message = Meldung
-report.invoker.format.percent = 0.0\u00A0%
-report.invoker.format.seconds = 0.0\u00A0s
+report.invoker.description=Bericht \u00FCber die Build-Ergebnisse der
Maven-Ausf\u00FChrungen.
+report.invoker.title=Invoker-Bericht
+report.invoker.summary.title=Zusammenfassung
+report.invoker.summary.builds=Builds
+report.invoker.summary.success=Erfolge
+report.invoker.summary.failures=Fehlschl\u00E4ge
+report.invoker.summary.skipped=Ausgelassen
+report.invoker.summary.successrate=Erfolgsrate
+report.invoker.summary.time=Zeit
+report.invoker.detail.title=Build-Details
+report.invoker.detail.name=Name
+report.invoker.detail.result=Ergebnis
+report.invoker.detail.time=Zeit
+report.invoker.detail.message=Meldung
+report.invoker.format.percent=0.0\u00A0%
diff --git a/src/main/resources/invoker-report_fr.properties
b/src/main/resources/invoker-report_fr.properties
index 1d3393a..7da545a 100644
--- a/src/main/resources/invoker-report_fr.properties
+++ b/src/main/resources/invoker-report_fr.properties
@@ -15,22 +15,19 @@
# specific language governing permissions and limitations
# under the License.
-report.invoker.result.description = R�sultat des invocations de Maven
-report.invoker.result.name = Invoker R�sultat de builds
-report.invoker.result.title = Invoker Rapport
-report.invoker.summary.title = Sommaire
-report.invoker.summary.number = Builds
-report.invoker.summary.success = R�ussis
-report.invoker.summary.failed = Echecs
-report.invoker.summary.skipped = Ignor�s
-report.invoker.summary.success.rate = Taux de r�ussite
-report.invoker.summary.time.total = Dur�e totale
-report.invoker.summary.time.avg = Dur�e moyenne
-report.invoker.detail.title = D�tails de Build
-report.invoker.detail.name = Nom
-report.invoker.detail.result = R�sultat
-report.invoker.detail.time = Dur�e
-report.invoker.detail.message = Message
-report.invoker.format.percent = 0.0%
-report.invoker.format.seconds = 0.0\u00A0s
-report.invoker.format.name_with_description = {0} : {1}
+report.invoker.description=R�sultat des invocations de Maven
+report.invoker.title=Invoker Rapport
+report.invoker.summary.title=Sommaire
+report.invoker.summary.builds=Builds
+report.invoker.summary.success=R�ussis
+report.invoker.summary.failures=Echecs
+report.invoker.summary.skipped=Ignor�s
+report.invoker.summary.successrate=Taux de r�ussite
+report.invoker.summary.time=Dur�e
+report.invoker.detail.title=D�tails de Build
+report.invoker.detail.name=Nom
+report.invoker.detail.result=R�sultat
+report.invoker.detail.time=Dur�e
+report.invoker.detail.message=Message
+report.invoker.format.percent=0.0\u00A0%
+report.invoker.format.name_with_description={0} : {1}