From b71ca330e16e21683d3179c38038d82b8a01eeb8 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 1 Jul 2018 09:01:01 +0200 Subject: [PATCH 01/60] Add available report formats to error message --- .../itsallcode/openfasttrace/report/ReportFormat.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/report/ReportFormat.java b/src/main/java/org/itsallcode/openfasttrace/report/ReportFormat.java index 0a76fa83..df1058fa 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/ReportFormat.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/ReportFormat.java @@ -1,5 +1,9 @@ package org.itsallcode.openfasttrace.report; +import static java.util.stream.Collectors.joining; + +import java.util.Arrays; + /*- * #%L * OpenFastTrace @@ -55,6 +59,11 @@ public static ReportFormat parse(final String format) return value; } } - throw new IllegalArgumentException("Unknown report format \"" + format + "\""); + final String availableValues = Arrays.stream(values()) // + .map(ReportFormat::toString) // + .map(s -> '"' + s + '"') // + .collect(joining(", ")); + throw new IllegalArgumentException( + "Unknown report format \"" + format + "\". Supported formats: " + availableValues); } } From f4e920036c1c55c298870621d31c5826476a12ce Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 1 Jul 2018 10:15:28 +0200 Subject: [PATCH 02/60] Add download instructions to README.md --- README.md | 64 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1f897375..bf6d4edf 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,6 @@ Sonarcloud status: -## Installation - -### Dependencies - [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=alert_status)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=bugs)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) [![Code smells](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=code_smells)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) @@ -26,19 +22,53 @@ Sonarcloud status: ## Project Information - * ![Contributing guide](CONTRIBUTING.md) * ![OpenFastTrace stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories) * ![Command Line Usage](doc/usage.txt) * ![Design](doc/design.md) * ![System Requirements](doc/system_requirements.md) +## Download -### On Linux +Download the executable jar at [jcenter](https://jcenter.bintray.com/org/itsallcode/openfasttrace/): -#### Ubuntu or Debian +* [openfasttrace-1.0.0.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.0.0/:openfasttrace-1.0.0.jar) - apt-get install openjdk-8-jre +### Maven + +To use OpenFastTrace as a dependency in your maven project add this to your `pom.xml`: + +```xml + + + central + bintray + http://jcenter.bintray.com + + + + + + org.itsallcode + openfasttrace + 1.0.0 + compile + + +``` + +### Gradle + +To use OpenFastTrace as a dependency in your gradle project: + +```groovy +repositories { + jcenter() +} +dependencies { + compile "org.itsallcode:openfasttrace:1.0.0" +} +``` ## Using OpenFastTrace @@ -50,9 +80,9 @@ Check the [user guide](doc/user_guide.md) for information on how to use OpenFast OpenFastTrace only needs a Java 8 (or later) runtime environment to run. -### Installation on Linux +#### Installation of runtime dependencies on Linux -#### Ubuntu or Debian +##### Ubuntu or Debian If you just want to run OFT: @@ -62,7 +92,6 @@ If you want to build OFT: apt-get install openjdk-8-jdk maven - ## Development ### Build Time Dependencies @@ -139,14 +168,15 @@ mvn -DwithHistory org.pitest:pitest-maven:mutationCoverage ``` -2. Update version in `pom.xml`, commit and push. -3. Run command +1. Checkout the `develop` branch. +1. Update version in `pom.xml` and `README.md`, commit and push. +1. Run command ```bash mvn deploy ``` -4. Create a [release](https://github.com/itsallcode/openfasttrace/releases) on GitHub. -5. Sign in at [bintray.com](https://bintray.com) -6. Go to the [bintray project page](https://bintray.com/itsallcode/itsallcode/openfasttrace) -7. There should be a notice saying "You have 6 unpublished item(s) for this package". Click the "Publish" link. +1. Create a [release](https://github.com/itsallcode/openfasttrace/releases) on GitHub. +1. Sign in at [bintray.com](https://bintray.com) +1. Go to the [bintray project page](https://bintray.com/itsallcode/itsallcode/openfasttrace) +1. There should be a notice saying "You have 6 unpublished item(s) for this package". Click the "Publish" link. Binaries will be available for download at [jcenter](https://jcenter.bintray.com/org/itsallcode/openfasttrace/) From da1816dc17dbf379988efc68dde42cc29280c87b Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 1 Jul 2018 10:25:19 +0200 Subject: [PATCH 03/60] Add a short description about requirement tracing to README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf6d4edf..13c2ca05 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ # OFT logo OpenFastTrace +## What is OpenFastTrace? + +OpenFastTrace is a requirement tracing suite. Requirement tracing helps you keeping track of whether you actually implemented everything you planned to in your specifications. It also identifies obsolete parts of your product and helps you getting rid of them. + +You can learn more about requirement tracing and how to use OpenFastTrace in the [user guide](doc/user_guide.md). + +## Project Information + [![Build Status](https://travis-ci.org/itsallcode/openfasttrace.svg)](https://travis-ci.org/itsallcode/openfasttrace) [![Circle CI](https://circleci.com/gh/itsallcode/openfasttrace.svg?style=svg)](https://circleci.com/gh/itsallcode/openfasttrace) [![codecov](https://codecov.io/gh/itsallcode/openfasttrace/branch/develop/graph/badge.svg)](https://codecov.io/gh/itsallcode/openfasttrace) @@ -20,8 +28,6 @@ Sonarcloud status: [![Technical Dept](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=sqale_index)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) -## Project Information - * ![Contributing guide](CONTRIBUTING.md) * ![OpenFastTrace stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories) * ![Command Line Usage](doc/usage.txt) From eb62747b266b5095559cf00230907b468fcb2b37 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 1 Jul 2018 10:31:34 +0200 Subject: [PATCH 04/60] Fix links to project info (remove broken image tag) --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 13c2ca05..74b5d1f0 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,11 @@ Sonarcloud status: [![Technical Dept](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=sqale_index)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) -* ![Contributing guide](CONTRIBUTING.md) -* ![OpenFastTrace stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories) -* ![Command Line Usage](doc/usage.txt) -* ![Design](doc/design.md) -* ![System Requirements](doc/system_requirements.md) +* [Contributing guide](CONTRIBUTING.md) +* [OpenFastTrace stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories) +* [Command Line Usage](doc/usage.txt) +* [Design](doc/design.md) +* [System Requirements](doc/system_requirements.md) ## Download From 30961dfc9f4c422b4488621e1eac60428858c7e3 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 1 Jul 2018 10:31:52 +0200 Subject: [PATCH 05/60] Add link to user guide to project info --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 74b5d1f0..2f4cccef 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Sonarcloud status: * [Contributing guide](CONTRIBUTING.md) * [OpenFastTrace stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories) +* [User Guide](doc/user_guide.md) * [Command Line Usage](doc/usage.txt) * [Design](doc/design.md) * [System Requirements](doc/system_requirements.md) From 3b447bb59f3d142e634f5ba442036d22f2425d9c Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 1 Jul 2018 10:32:48 +0200 Subject: [PATCH 06/60] Fix broken download link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f4cccef..2f6c1316 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Sonarcloud status: Download the executable jar at [jcenter](https://jcenter.bintray.com/org/itsallcode/openfasttrace/): -* [openfasttrace-1.0.0.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.0.0/:openfasttrace-1.0.0.jar) +* [openfasttrace-1.0.0.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.0.0/openfasttrace-1.0.0.jar) ### Maven From de885f71c119cf3f50d865574af38641e1194428 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sun, 1 Jul 2018 17:03:45 +0200 Subject: [PATCH 07/60] Added blog link --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2f6c1316..bd264ff4 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Sonarcloud status: [![Technical Dept](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=sqale_index)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=org.itsallcode%3Aopenfasttrace%3Adevelop&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=org.itsallcode%3Aopenfasttrace%3Adevelop) +* [Blog](https://blog.itsallcode.org/) * [Contributing guide](CONTRIBUTING.md) * [OpenFastTrace stories](https://github.com/itsallcode/openfasttrace/wiki/OFT-Stories) * [User Guide](doc/user_guide.md) From ff4348f633acb6d74b52c1f8cc0bf136b211e595 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 1 Jul 2018 21:04:14 +0200 Subject: [PATCH 08/60] Configure finest log level for tests to improve code coverage for log messages --- .../markdown/TestMarkdownImporterFactory.java | 2 - .../testutil/log/LogHandlerRule.java | 112 ++++++++++++++++++ .../testutil/log/NoOpLoggingHandler.java | 56 +++++++++ src/test/resources/logging.properties | 12 +- 4 files changed, 173 insertions(+), 9 deletions(-) create mode 100644 src/test/java/org/itsallcode/openfasttrace/testutil/log/LogHandlerRule.java create mode 100644 src/test/java/org/itsallcode/openfasttrace/testutil/log/NoOpLoggingHandler.java diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/markdown/TestMarkdownImporterFactory.java b/src/test/java/org/itsallcode/openfasttrace/importer/markdown/TestMarkdownImporterFactory.java index e8d08443..96e5b6f5 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/markdown/TestMarkdownImporterFactory.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/markdown/TestMarkdownImporterFactory.java @@ -22,13 +22,11 @@ * #L% */ - import static java.util.Arrays.asList; import java.util.List; import org.itsallcode.openfasttrace.importer.ImporterFactoryTestBase; -import org.itsallcode.openfasttrace.importer.markdown.MarkdownImporterFactory; /** * Tests for {@link MarkdownImporterFactory} diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/log/LogHandlerRule.java b/src/test/java/org/itsallcode/openfasttrace/testutil/log/LogHandlerRule.java new file mode 100644 index 00000000..d980dd47 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/testutil/log/LogHandlerRule.java @@ -0,0 +1,112 @@ +package org.itsallcode.openfasttrace.testutil.log; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +import java.util.logging.*; + +import org.junit.rules.ExternalResource; +import org.junit.rules.TestRule; + +/** + * This junit {@link TestRule} sets a temporary log level and a + * {@link NoOpLoggingHandler} during tests and restores the original state after + * the test. This allows you to run the tests with all log messages but without + * the overhead of spamming the log. + */ +public class LogHandlerRule extends ExternalResource +{ + private static Logger LOG = Logger.getLogger(LogHandlerRule.class.getName()); + private final Logger rootLogger; + private final Handler loggingHandler; + private final Level logLevel; + private Level originalLogLevel; + + private LogHandlerRule(final Handler loggingHandler, final Level logLevel) + { + this.logLevel = logLevel; + this.rootLogger = getRootLogger(); + this.loggingHandler = loggingHandler; + } + + private static Logger getRootLogger() + { + return LogManager.getLogManager().getLogger(""); + } + + /** + * Creates a new {@link LogHandlerRule} that uses log level + * {@link Level#ALL}. + */ + public static LogHandlerRule withNoOpHandler() + { + final NoOpLoggingHandler handler = new NoOpLoggingHandler(); + return new LogHandlerRule(handler, Level.ALL); + } + + @Override + protected void before() + { + installHandler(); + configureLogLevel(); + } + + private void installHandler() + { + LOG.finest(() -> "Installing logging handler " + this.loggingHandler); + this.rootLogger.addHandler(this.loggingHandler); + } + + private void configureLogLevel() + { + this.originalLogLevel = this.rootLogger.getLevel(); + LOG.finest(() -> "Configure log level " + this.logLevel + ", original level was " + + this.originalLogLevel); + this.rootLogger.setLevel(this.logLevel); + } + + @Override + protected void after() + { + restoreLogLevel(); + uninstallHandler(); + } + + private void restoreLogLevel() + { + LOG.finest(() -> "Restore original log level " + this.originalLogLevel); + this.rootLogger.setLevel(this.originalLogLevel); + } + + private void uninstallHandler() + { + final Handler[] handlers = this.rootLogger.getHandlers(); + for (final Handler handler : handlers) + { + if (handler == this.loggingHandler) + { + LOG.finest(() -> "Uninstalling logging handler " + this.loggingHandler); + this.rootLogger.removeHandler(handler); + } + } + } + +} diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/log/NoOpLoggingHandler.java b/src/test/java/org/itsallcode/openfasttrace/testutil/log/NoOpLoggingHandler.java new file mode 100644 index 00000000..4193461e --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/testutil/log/NoOpLoggingHandler.java @@ -0,0 +1,56 @@ +package org.itsallcode.openfasttrace.testutil.log; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +import java.util.logging.Handler; +import java.util.logging.LogRecord; + +/** + * Logging {@link Handler} that ignores all log messages. This is useful for + * testing with the highest log level but without spamming the console with log + * messages. + */ +public class NoOpLoggingHandler extends Handler +{ + + public NoOpLoggingHandler() + { + } + + @Override + public void publish(final LogRecord record) + { + // empty + } + + @Override + public void flush() + { + // empty + } + + @Override + public void close() + { + // empty + } +} diff --git a/src/test/resources/logging.properties b/src/test/resources/logging.properties index 164a16e1..795042fd 100644 --- a/src/test/resources/logging.properties +++ b/src/test/resources/logging.properties @@ -19,15 +19,13 @@ # . # #L% ### -handlers = java.util.logging.ConsoleHandler +handlers = java.util.logging.ConsoleHandler org.itsallcode.openfasttrace.testutil.log.NoOpLoggingHandler .level = INFO -java.util.logging.ConsoleHandler.level = FINEST +java.util.logging.ConsoleHandler.level = INFO java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.encoding = UTF-8 java.util.logging.SimpleFormatter.format = %1$tF %1$tT [%4$s] %2$s - %5$s %6$s%n -org.itsallcode.openfasttrace.level = INFO -org.itsallcode.openfasttrace.exporter.level = INFO -org.itsallcode.openfasttrace.importer.level = INFO -org.itsallcode.openfasttrace.importer.legacytag.config.PathConfig.level = FINEST -org.itsallcode.openfasttrace.importer.legacytag.LegacyTagImporterFactory.level = FINEST +org.itsallcode.openfasttrace.testutil.log.NoOpLoggingHandler.level = FINEST + +org.itsallcode.openfasttrace.level = FINEST From 8db9e11df0df2f1496b7d4a684d5ad9d1d09c839 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 7 Jul 2018 09:58:30 +0200 Subject: [PATCH 09/60] #155 Configure javadoc plugin --- pom.xml | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1affefd7..e4ea88fa 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.itsallcode openfasttrace - 1.0.0 + 1.0.1 OpenFastTrace Free requirement tracking suite https://github.com/itsallcode/openfasttrace @@ -24,6 +24,8 @@ bintray-openfasttrack-maven-repo https://api.bintray.com/maven/itsallcode/itsallcode/openfasttrace/;publish=0 + + @@ -114,6 +116,26 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.1 + + + attach-javadocs + + jar + + + + + UTF-8 + + true + false + false + + org.jacoco jacoco-maven-plugin From 5e07272a1b95bd8073ba5641f08d15036f9ab3f6 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 7 Jul 2018 10:32:56 +0200 Subject: [PATCH 10/60] #155 Add information required to publish to maven central --- pom.xml | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e4ea88fa..aebf0f23 100644 --- a/pom.xml +++ b/pom.xml @@ -3,10 +3,38 @@ 4.0.0 org.itsallcode openfasttrace - 1.0.1 + 1.0.2 OpenFastTrace Free requirement tracking suite https://github.com/itsallcode/openfasttrace + + + GNU General Public License v3.0 + https://www.gnu.org/licenses/gpl-3.0.html + repo + + + + + redcatbear + https://github.com/redcatbear + itsallcode + https://github.com/itsallcode + + + sascha15432 + https://github.com/sascha15432 + itsallcode + https://github.com/itsallcode + + + kaklakariada + https://github.com/kaklakariada + itsallcode + https://github.com/itsallcode + github@chp1.net + + scm:git:https://github.com/itsallcode/openfasttrace.git scm:git:https://github.com/itsallcode/openfasttrace.git From d77d15d7a0294336e144c964530157e3437e7d49 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 7 Jul 2018 11:27:53 +0200 Subject: [PATCH 11/60] #155 Describe maven central sync --- README.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bd264ff4..8cefb446 100644 --- a/README.md +++ b/README.md @@ -47,14 +47,6 @@ Download the executable jar at [jcenter](https://jcenter.bintray.com/org/itsallc To use OpenFastTrace as a dependency in your maven project add this to your `pom.xml`: ```xml - - - central - bintray - http://jcenter.bintray.com - - - org.itsallcode @@ -188,3 +180,5 @@ mvn -DwithHistory org.pitest:pitest-maven:mutationCoverage 1. Sign in at [bintray.com](https://bintray.com) 1. Go to the [bintray project page](https://bintray.com/itsallcode/itsallcode/openfasttrace) 1. There should be a notice saying "You have 6 unpublished item(s) for this package". Click the "Publish" link. Binaries will be available for download at [jcenter](https://jcenter.bintray.com/org/itsallcode/openfasttrace/) +1. Publish to maven central by clicking the "Sync" button at https://bintray.com/itsallcode/itsallcode/openfasttrace#central. After some time the new version will appear at https://repo1.maven.org/maven2/org/itsallcode/openfasttrace/. + From 74fa0344b8fe8d6947f0a31e9e8e3709f2e4d0c8 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Mon, 9 Jul 2018 21:09:35 +0200 Subject: [PATCH 12/60] #145: Improved tag filter up to API. Fixed tag reading bug in Markdown importer. Task-Url: https://github.com/itsallcode/openfasttrace/issues/145 --- doc/design.md | 17 +- doc/system_requirements.md | 17 +- doc/usage.txt | 6 +- doc/user_guide.md | 15 ++ launch/OFT - Run all tests.launch | 66 +++---- .../openfasttrace/FilterSettings.java | 31 ++- .../importer/SpecificationListBuilder.java | 6 +- .../importer/markdown/MarkdownImporter.java | 6 +- src/main/resources/openfasttrace_logo.svg | 181 ++++++++---------- .../openfasttrace/cli/TestCliArguments.java | 15 +- .../TestSpecificationListBuilder.java | 73 ++++--- .../openfasttrace/mode/ITestReporter.java | 26 --- .../mode/ITestReporterWithFilter.java | 105 ++++++++++ 13 files changed, 359 insertions(+), 205 deletions(-) create mode 100644 src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java diff --git a/doc/design.md b/doc/design.md index 72842c38..ff99dd9b 100644 --- a/doc/design.md +++ b/doc/design.md @@ -140,14 +140,25 @@ Covers: Needs: impl, utest, itest -#### Filtering by Tags Import +#### Filtering by Tags During Import `dsn~filtering-by-tags-during-import~1` -When OFT is configured to restrict inclusion to tags the [specification list builder](#specification-list-builder) imports a specification item only if at least one of it tags is contained in the configured set of tags. +The [specification list builder](#specification-list-builder) can be configured to import a specification item only if at least one of its tags is contained in the configured set of tags. Covers: -* `req~include-only-tags~1` +* `req~include-items-where-at-least-on-tag-matches~1` + +Needs: impl, utest, itest + +#### Filtering by Tags or no Tags During Import +`dsn~filtering-by-tags-or-no-tags-during-import~1` + +The [specification list builder](#specification-list-builder) can be configured to import a specification item only if it either has no tags or at least one of its tags is contained in the configured set of tags. + +Covers: + +* `req~include-items-that-do-not-have-tags-or-where-at-least-one-tag-matches~1` Needs: impl, utest, itest diff --git a/doc/system_requirements.md b/doc/system_requirements.md index 37604aca..0fda8950 100644 --- a/doc/system_requirements.md +++ b/doc/system_requirements.md @@ -414,10 +414,21 @@ Covers: Needs: dsn -#### Include Only Tags -`req~include-only-tags~1` +#### Include Items Where at Least One Tag Matches +`req~include-items-where-at-least-on-tag-matches~1` -OFT gives users the option to include only specification items contained in configurable set of tags during processing. +OFT gives users the option to include only specification items that have at least one tag from a configurable set of tags during processing. + +Covers: + +* [feat~requirement-tracing~1](#requirement-tracing) + +Needs: dsn + +#### Include Items That Don't Have Tags Or Where at Least One Tag Matches +`req~include-items-that-do-not-have-tags-or-where-at-least-one-tag-matches~1` + +OFT gives users the option to include only specification items that either do not have tags or have at least one tag from a configurable set of tags during processing. Covers: diff --git a/doc/usage.txt b/doc/usage.txt index a18545b7..9420757b 100644 --- a/doc/usage.txt +++ b/doc/usage.txt @@ -22,8 +22,12 @@ Common options: -i, --ignore-artifact-types Define a comma-separated list of artifact types to be ignored during import. -n, --newline format Newline format one of "unix", "windows", "oldmac" - -a, --wanted-artifact-types Filter out all but the artifact types in the + -a, --wanted-artifact-types Import only specification items contained in the comma-separated list + -t, --wanted-tags Import only specification items that have at + least one tag contained in the comma-separated + list. Add a single underscore as first item in + the list to also import items without any tags. Returns: 0 on success diff --git a/doc/user_guide.md b/doc/user_guide.md index 04d9ba8b..28d5d51c 100644 --- a/doc/user_guide.md +++ b/doc/user_guide.md @@ -275,6 +275,11 @@ Wan and Wu from the web service team in our example would run an OFT convert job This tells OFT to read all known specification files from the directory "import/arch" and filter by a list of tags. The result is a list of requirements that match the tag filter. +If you want to also import specification items that do not have any tags, add a single underscore "_" as the first entry in the comma-separated list of tags: + + oft convert -t _,AuthenticationProvider,ServiceDiscovery,MapProvider import/arch/ > arch_filtered_by_web_services.xml + + ### Tracing the Whole Chain If you plan to assess the coverage state of your product as a whole, you need to trace the full chain including all artifact. @@ -337,6 +342,16 @@ Where `command` is one of and `option` is one or more of the options listed below. +#### Import options + + -a, --wanted-artifact-types [,...] + +Import only specification items where the artifact type matches one of the listed types. + + -t, --wanted-tags [_,][,...] + +Import only specification items that have at least one of the listed tags. If you add a single underscore "_" as first entry in the list, specification items that no tags at all are also imported. + #### Tracing options -o, --output-format diff --git a/launch/OFT - Run all tests.launch b/launch/OFT - Run all tests.launch index 6e8e8937..245ab39d 100644 --- a/launch/OFT - Run all tests.launch +++ b/launch/OFT - Run all tests.launch @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/itsallcode/openfasttrace/FilterSettings.java b/src/main/java/org/itsallcode/openfasttrace/FilterSettings.java index 996ae28e..88f36939 100644 --- a/src/main/java/org/itsallcode/openfasttrace/FilterSettings.java +++ b/src/main/java/org/itsallcode/openfasttrace/FilterSettings.java @@ -33,11 +33,13 @@ public final class FilterSettings { private final Set artifactTypes; private final Set tags; + private final boolean withoutTags; private FilterSettings(final Builder builder) { this.artifactTypes = builder.artifactTypes; this.tags = builder.tags; + this.withoutTags = builder.withoutTags; } /** @@ -60,6 +62,14 @@ public Set getTags() return this.tags; } + /** + * @return true if the filter allows items with no tags + */ + public boolean withoutTags() + { + return this.withoutTags; + } + /** * Check if the artifact type filter is set. * @@ -77,7 +87,7 @@ public boolean isArtifactTypeCriteriaSet() */ public boolean isTagCriteriaSet() { - return this.tags != null && !this.tags.isEmpty(); + return !this.withoutTags() || (this.tags != null && !this.tags.isEmpty()); } /** @@ -98,6 +108,7 @@ public int hashCode() int result = 1; result = prime * result + ((this.artifactTypes == null) ? 0 : this.artifactTypes.hashCode()); + result = prime * result + (this.withoutTags ? 1231 : 1237); result = prime * result + ((this.tags == null) ? 0 : this.tags.hashCode()); return result; } @@ -130,6 +141,10 @@ else if (!this.artifactTypes.equals(other.artifactTypes)) { return false; } + if (this.withoutTags != other.withoutTags) + { + return false; + } if (this.tags == null) { if (other.tags != null) @@ -162,6 +177,7 @@ public static class Builder { private Set artifactTypes = Collections.emptySet(); private Set tags = Collections.emptySet(); + private boolean withoutTags = true; /** * Set the list of artifact types that the filter matches. @@ -189,6 +205,19 @@ public Builder tags(final Set tags) return this; } + /** + * Configure if filter allows items that have no tags. + * + * @param withoutTags + * true to match items without any tags + * @return this for fluent programming + */ + public Builder withoutTags(final boolean noTags) + { + this.withoutTags = noTags; + return this; + } + /** * Build an instance of type {@link FilterSettings}. * diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/SpecificationListBuilder.java b/src/main/java/org/itsallcode/openfasttrace/importer/SpecificationListBuilder.java index 81c15653..05708423 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/SpecificationListBuilder.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/SpecificationListBuilder.java @@ -206,13 +206,15 @@ private SpecificationItem createNewSpecificationItem() private boolean isAccepted(final SpecificationItem item) { return isAcceptedArtifactType(item.getId().getArtifactType()) - && containsAtLeastOneAcceptedTag(item.getTags()); + && matchesTagsCriteria(item.getTags()); } // [impl->dsn~filtering-by-tags-during-import~1] - private boolean containsAtLeastOneAcceptedTag(final List tags) + // [impl->dsn~filtering-by-tags-or-no-tags-during-import~1] + private boolean matchesTagsCriteria(final List tags) { return !this.filterSettings.isTagCriteriaSet() + || (this.filterSettings.withoutTags() && tags.isEmpty()) || !Collections.disjoint(this.filterSettings.getTags(), tags); } diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/markdown/MarkdownImporter.java b/src/main/java/org/itsallcode/openfasttrace/importer/markdown/MarkdownImporter.java index 35f99b9f..8ff51b2e 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/markdown/MarkdownImporter.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/markdown/MarkdownImporter.java @@ -76,9 +76,9 @@ class MarkdownImporter implements Importer transition(DESCRIPTION, DEPENDS , MdPattern.DEPENDS , this::endDescription ), transition(DESCRIPTION, NEEDS , MdPattern.NEEDS_INT , () -> {endDescription(); addNeeds();} ), transition(DESCRIPTION, NEEDS , MdPattern.NEEDS , this::endDescription ), - transition(DESCRIPTION, DESCRIPTION, MdPattern.EVERYTHING , this::appendDescription ), transition(DESCRIPTION, TAGS , MdPattern.TAGS_INT , this::addTag ), transition(DESCRIPTION, TAGS , MdPattern.TAGS , () -> {} ), + transition(DESCRIPTION, DESCRIPTION, MdPattern.EVERYTHING , this::appendDescription ), transition(RATIONALE , SPEC_ITEM , MdPattern.ID , () -> {endRationale(); beginItem();} ), @@ -88,9 +88,9 @@ class MarkdownImporter implements Importer transition(RATIONALE , DEPENDS , MdPattern.DEPENDS , this::endRationale ), transition(RATIONALE , NEEDS , MdPattern.NEEDS_INT , () -> {endRationale(); addNeeds();} ), transition(RATIONALE , NEEDS , MdPattern.NEEDS , this::endRationale ), - transition(RATIONALE , RATIONALE , MdPattern.EVERYTHING , this::appendRationale ), transition(RATIONALE , TAGS , MdPattern.TAGS_INT , this::addTag ), transition(RATIONALE , TAGS , MdPattern.TAGS , () -> {} ), + transition(RATIONALE , RATIONALE , MdPattern.EVERYTHING , this::appendRationale ), transition(COMMENT , SPEC_ITEM , MdPattern.ID , () -> {endComment(); beginItem();} ), transition(COMMENT , TITLE , MdPattern.TITLE , () -> {endComment(); endItem(); rememberTitle(); } ), @@ -99,9 +99,9 @@ class MarkdownImporter implements Importer transition(COMMENT , NEEDS , MdPattern.NEEDS_INT , () -> {endComment(); addNeeds();} ), transition(COMMENT , NEEDS , MdPattern.NEEDS , this::endComment ), transition(COMMENT , RATIONALE , MdPattern.RATIONALE , () -> {endComment(); beginRationale();} ), - transition(COMMENT , COMMENT , MdPattern.EVERYTHING , this::appendComment ), transition(COMMENT , TAGS , MdPattern.TAGS_INT , this::addTag ), transition(COMMENT , TAGS , MdPattern.TAGS , () -> {} ), + transition(COMMENT , COMMENT , MdPattern.EVERYTHING , this::appendComment ), // [impl->dsn~md.covers-list~1] diff --git a/src/main/resources/openfasttrace_logo.svg b/src/main/resources/openfasttrace_logo.svg index 758f35c5..64d4ff43 100644 --- a/src/main/resources/openfasttrace_logo.svg +++ b/src/main/resources/openfasttrace_logo.svg @@ -1,4 +1,4 @@ - + - - + + - - - - - - - - - - - - - - - - - - - + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java b/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java index d31e31e0..10462a61 100644 --- a/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java +++ b/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java @@ -182,7 +182,7 @@ public void testSetI() // [utest->dsn~filtering-by-tags-during-import~1] @Test - public void testSetIngnoreTags() + public void testSetWantedTags() { final String value = "client,server"; assertThat(BEFORE_SETTER, this.arguments.getWantedTags(), emptyIterable()); @@ -190,4 +190,15 @@ public void testSetIngnoreTags() assertThat(AFTER_SETTER, this.arguments.getWantedTags(), containsInAnyOrder("client", "server")); } -} + + // [utest->dsn~filtering-by-tags-or-no-tags-during-import~1] + @Test + public void testSetWantedTagsIncludingNone() + { + final String value = "_,client,server"; + assertThat(BEFORE_SETTER, this.arguments.getWantedTags(), emptyIterable()); + this.arguments.setWantedTags(value); + assertThat(AFTER_SETTER, this.arguments.getWantedTags(), + containsInAnyOrder("_", "client", "server")); + } +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/TestSpecificationListBuilder.java b/src/test/java/org/itsallcode/openfasttrace/importer/TestSpecificationListBuilder.java index 0b4e9097..748305b2 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/TestSpecificationListBuilder.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/TestSpecificationListBuilder.java @@ -27,9 +27,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import org.itsallcode.openfasttrace.FilterSettings; @@ -181,40 +179,55 @@ public void testDuplicateIdNotIgnored() @Test public void testFilterSpecificationItemsByTags() { - final SpecificationListBuilder builder = createListBuilderFilteringByTags("client", - "server"); - builder.beginSpecificationItem(); - final SpecificationItemId idA = SpecificationItemId.createId("dsn", "in-A", 1); - builder.setId(idA); - builder.addTag("client"); - builder.addTag("database"); - builder.endSpecificationItem(); - builder.beginSpecificationItem(); - final SpecificationItemId idB = SpecificationItemId.createId("dsn", "in-B", 1); - builder.setId(idB); - builder.addTag("server"); - builder.addTag("database"); - builder.endSpecificationItem(); - builder.beginSpecificationItem(); - final SpecificationItemId idC = SpecificationItemId.createId("dsn", "out-C", 1); - builder.setId(idC); - builder.addTag("exporter"); - builder.addTag("database"); - builder.endSpecificationItem(); - builder.beginSpecificationItem(); - final SpecificationItemId idD = SpecificationItemId.createId("dsn", "out-D", 1); - builder.setId(idD); - builder.endSpecificationItem(); + final Set wantedTags = new HashSet<>(); + wantedTags.add("client"); + wantedTags.add("server"); + final FilterSettings filterSettings = new FilterSettings.Builder() // + .tags(wantedTags) // + .withoutTags(false) // + .build(); + final SpecificationListBuilder builder = SpecificationListBuilder + .createWithFilter(filterSettings); + addItemWithTags(builder, "in-A", "client", "database"); + addItemWithTags(builder, "in-B", "server", "database"); + addItemWithTags(builder, "out-C", "exporter", "database"); + addItemWithTags(builder, "out-D"); final List items = builder.build(); assertThat(items.stream().map(item -> item.getId().getName()).collect(Collectors.toList()), containsInAnyOrder("in-A", "in-B")); } - private SpecificationListBuilder createListBuilderFilteringByTags(final String... tags) + private void addItemWithTags(final SpecificationListBuilder builder, final String name, + final String... tags) { + builder.beginSpecificationItem(); + final SpecificationItemId idA = SpecificationItemId.createId("dsn", name, 1); + builder.setId(idA); + for (final String tag : tags) + { + builder.addTag(tag); + } + builder.endSpecificationItem(); + } + + // [utest->dsn~filtering-by-tags-or-no-tags-during-import~1] + @Test + public void testFilterSpecificationItemsByTagsIncludingNoTags() + { + final Set wantedTags = new HashSet<>(); + wantedTags.add("client"); + wantedTags.add("server"); final FilterSettings filterSettings = new FilterSettings.Builder() // - .tags(new HashSet<>(Arrays.asList(tags))) // + .tags(wantedTags) // .build(); - return SpecificationListBuilder.createWithFilter(filterSettings); + final SpecificationListBuilder builder = SpecificationListBuilder + .createWithFilter(filterSettings); + addItemWithTags(builder, "in-A", "client", "database"); + addItemWithTags(builder, "in-B", "server", "database"); + addItemWithTags(builder, "out-C", "exporter", "database"); + addItemWithTags(builder, "in-D"); + final List items = builder.build(); + assertThat(items.stream().map(item -> item.getId().getName()).collect(Collectors.toList()), + containsInAnyOrder("in-A", "in-B", "in-D")); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java index ec2da7fe..e2a22bf6 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java @@ -137,30 +137,4 @@ private long countItemsOfArtifactTypeInTrace(final String artifactType, final Tr }) // .count(); } - - // [itest->dsn~filtering-by-tags-during-import~1] - @Test - public void testFilterAllowsTagsClientAndServer() - { - final Set tags = new HashSet<>(Arrays.asList("client", "server")); - this.reporter.addInputs(this.docDir); - final Trace fullTrace = this.reporter.trace(); - final String filteredOutTag = "database"; - assertThat("Number of items with tag \"" + filteredOutTag + "\" in regular trace", - countItemsWithTagInTrace(filteredOutTag, fullTrace), greaterThan(0L)); - final Trace trace = this.reporter // - .setFilters(new FilterSettings.Builder().tags(tags).build())// - .trace(); - assertThat("Number of items with tag \"" + filteredOutTag + "\" in filted trace", - countItemsWithTagInTrace(filteredOutTag, trace), equalTo(0L)); - } - - private long countItemsWithTagInTrace(final String tag, final Trace trace) - { - return trace.getItems().stream() // - .filter(item -> { - return item.getTags().contains(tag); - }) // - .count(); - } } diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java new file mode 100644 index 00000000..1c8f052d --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java @@ -0,0 +1,105 @@ +package org.itsallcode.openfasttrace.mode; + +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; + +import org.itsallcode.openfasttrace.FilterSettings; +import org.itsallcode.openfasttrace.Reporter; +import org.itsallcode.openfasttrace.core.Trace; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class ITestReporterWithFilter +{ + public static final String SPECIFICATION = String.join(System.lineSeparator(), // + "`feat~a~1`", // + "", // + "I am a feature", // + "", // + "`req~b~2`", // + "", // + "A user requirement", // + "", // + "Tags: tag1, tag2", // + "", // + "`dsn~c~3`", // + "", // + "Design", // + "", // + "Tags: tag1, tag3", // + "", // + "`impl~d~4`", // + "", // + "An implementation", // + "", // + "Tags: tag2, tag3", // + "", // + "`utest~e~5`", // + "", // + "A unit test", // + "", // + "Tags: tag3"); + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + private Reporter reporter; + + @Before + public void before() throws IOException + { + final File specification = this.tempFolder.newFile("spec.md"); + final PrintWriter writer = new PrintWriter(specification); + writer.print(SPECIFICATION); + writer.flush(); + writer.close(); + this.reporter = new ReportMode(); + this.reporter.addInputs(this.tempFolder.getRoot().toPath()); + } + + // [itest->dsn~filtering-by-tags-during-import~1] + @Test + public void testFilterWithAtLeastOneMatchingTag() + { + final FilterSettings filterSettings = new FilterSettings.Builder() // + .tags(new HashSet<>(Arrays.asList("tag1", "tag2"))) // + .withoutTags(false) // + .build(); + final List filteredIds = getIdsFromTraceWithFilterSettings(filterSettings); + assertThat(filteredIds, containsInAnyOrder("req~b~2", "dsn~c~3", "impl~d~4")); + } + + private List getIdsFromTraceWithFilterSettings(final FilterSettings filterSettings) + { + final Trace trace = this.reporter // + .setFilters(filterSettings) // + .trace(); + final List filteredIds = trace.getItems() // + .stream() // + .map(item -> item.getId().toString()) // + .collect(Collectors.toList()); + return filteredIds; + } + + // [itest->dsn~filtering-by-tags-or-no-tags-during-import~1] + @Test + public void testFilterWithAtLeastOneMatchingTagOrNoTags() + { + final FilterSettings filterSettings = new FilterSettings.Builder() // + .tags(new HashSet<>(Arrays.asList("tag1", "tag2"))) // + .build(); + final List filteredIds = getIdsFromTraceWithFilterSettings(filterSettings); + assertThat(filteredIds, containsInAnyOrder("feat~a~1", "req~b~2", "dsn~c~3", "impl~d~4")); + + } +} \ No newline at end of file From 3988ce7974adfcb46735559b195f73c982a2517b Mon Sep 17 00:00:00 2001 From: redcatbear Date: Mon, 9 Jul 2018 21:11:44 +0200 Subject: [PATCH 13/60] #145: Removed superfluous lines in Markdown test sample for tag filtering. Added missing license header. Task-Url: https://github.com/itsallcode/openfasttrace/issues/145 --- .../mode/ITestReporterWithFilter.java | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java index 1c8f052d..9711ca1d 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java @@ -1,5 +1,27 @@ package org.itsallcode.openfasttrace.mode; +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.junit.Assert.assertThat; @@ -23,31 +45,18 @@ public class ITestReporterWithFilter { public static final String SPECIFICATION = String.join(System.lineSeparator(), // "`feat~a~1`", // - "", // "I am a feature", // - "", // "`req~b~2`", // - "", // "A user requirement", // - "", // "Tags: tag1, tag2", // - "", // "`dsn~c~3`", // - "", // "Design", // - "", // "Tags: tag1, tag3", // - "", // "`impl~d~4`", // - "", // "An implementation", // - "", // "Tags: tag2, tag3", // - "", // "`utest~e~5`", // - "", // "A unit test", // - "", // "Tags: tag3"); @Rule @@ -102,4 +111,4 @@ public void testFilterWithAtLeastOneMatchingTagOrNoTags() assertThat(filteredIds, containsInAnyOrder("feat~a~1", "req~b~2", "dsn~c~3", "impl~d~4")); } -} \ No newline at end of file +} From c3e241e496549c8dc65b7d361faeee6338957133 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Tue, 10 Jul 2018 21:51:00 +0200 Subject: [PATCH 14/60] #145: Tags filter removes too many items Task-Url: https://github.com/itsallcode/openfasttrace/issues/145 --- pom.xml | 2 +- .../openfasttrace/cli/CliArguments.java | 1 + .../cli/commands/AbstractCommand.java | 37 +++++- .../openfasttrace/cli/ITestCliWithFilter.java | 112 ++++++++++++++++++ .../mode/ITestReporterWithFilter.java | 13 +- .../AbstractSpecificationFileBasedTest.java | 39 ++++++ 6 files changed, 190 insertions(+), 14 deletions(-) create mode 100644 src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java create mode 100644 src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java diff --git a/pom.xml b/pom.xml index 1affefd7..c20ce6f8 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ com.github.stefanbirkner system-rules - 1.17.2 + 1.18.0 test diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java b/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java index bdd9a741..83295080 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java @@ -41,6 +41,7 @@ */ public class CliArguments { + public static final String NO_TAGS_MARKER = "_"; private static final String CURRENT_DIRECTORY = "."; // [impl->dsn~cli.default-newline-format~1] private Newline newline = Newline.fromRepresentation(System.lineSeparator()); diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java index 2d53fafc..e5fbb7e5 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java @@ -27,6 +27,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.Set; import org.itsallcode.openfasttrace.FilterSettings; import org.itsallcode.openfasttrace.cli.CliArguments; @@ -56,8 +57,36 @@ public List toPaths(final List inputs) protected FilterSettings createFilterSettingsFromArguments() { - return new FilterSettings.Builder() // - .artifactTypes(this.arguments.getWantedArtifactTypes()) // - .build(); + final FilterSettings.Builder builder = new FilterSettings.Builder(); + setAttributeTypeFilter(builder); + setTagFilter(builder); + return builder.build(); } -} + + private void setAttributeTypeFilter(final FilterSettings.Builder builder) + { + if (this.arguments.getWantedArtifactTypes() != null + && !this.arguments.getWantedArtifactTypes().isEmpty()) + { + builder.artifactTypes(this.arguments.getWantedArtifactTypes()); + } + } + + private void setTagFilter(final FilterSettings.Builder builder) + { + final Set wantedTags = this.arguments.getWantedTags(); + if (wantedTags != null && !wantedTags.isEmpty()) + { + if (wantedTags.contains(CliArguments.NO_TAGS_MARKER)) + { + builder.withoutTags(true); + wantedTags.remove(CliArguments.NO_TAGS_MARKER); + } + else + { + builder.withoutTags(false); + } + builder.tags(wantedTags); + } + } +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java new file mode 100644 index 00000000..7ff68361 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java @@ -0,0 +1,112 @@ +package org.itsallcode.openfasttrace.cli; + +import static org.hamcrest.core.IsNot.not; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.io.IOException; + +import org.itsallcode.openfasttrace.testutil.AbstractSpecificationFileBasedTest; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.Assertion; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; +import org.junit.contrib.java.lang.system.SystemOutRule; +import org.junit.rules.TemporaryFolder; + +public class ITestCliWithFilter extends AbstractSpecificationFileBasedTest +{ + public static final String SPECIFICATION = String.join(System.lineSeparator(), // + "`feat~a~1`", // + "I am a feature", // + "`req~b~2`", // + "A user requirement", // + "Tags: tag1", // + "`dsn~c~3`", // + "Design", // + "Tags: tag2", // + "`impl~d~4`"); + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + @Rule + public final SystemOutRule systemOutRule = new SystemOutRule().enableLog(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + + private File specFile; + + @Before + public void before() throws IOException + { + this.specFile = this.tempFolder.newFile("spec.md"); + writeTextFile(this.specFile, SPECIFICATION); + this.exit.expectSystemExitWithStatus(0); + } + + // [itest->dsn~filtering-by-tags-during-import~1] + @Test + public void testFilterWithAtLeastOneMatchingTag() + { + this.exit.checkAssertionAfterwards(new Assertion() + { + @Override + public void checkAssertion() + { + final String stdOut = ITestCliWithFilter.this.systemOutRule.getLog(); + assertThat(stdOut, not(containsString("a<"))); + assertThat(stdOut, containsString("b<")); + assertThat(stdOut, not(containsString("c<"))); + } + }); + runWithArguments("convert", "-t", "tag1", this.specFile.toString()); + } + + private void runWithArguments(final String... args) + { + CliStarter.main(args); + } + + // [itest->dsn~filtering-by-tags-or-no-tags-during-import~1] + @Test + public void testFilterWithAtLeastOneMatchingTagOrNoTags() + { + this.exit.checkAssertionAfterwards(new Assertion() + { + @Override + public void checkAssertion() + { + final String stdOut = ITestCliWithFilter.this.systemOutRule.getLog(); + assertThat(stdOut, containsString("a<")); + assertThat(stdOut, containsString("b<")); + assertThat(stdOut, not(containsString("c<"))); + } + }); + runWithArguments("convert", "-t", "_,tag1", this.specFile.toString()); + } +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java index 9711ca1d..d8c97d07 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java @@ -25,9 +25,7 @@ import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.junit.Assert.assertThat; -import java.io.File; import java.io.IOException; -import java.io.PrintWriter; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -36,12 +34,13 @@ import org.itsallcode.openfasttrace.FilterSettings; import org.itsallcode.openfasttrace.Reporter; import org.itsallcode.openfasttrace.core.Trace; +import org.itsallcode.openfasttrace.testutil.AbstractSpecificationFileBasedTest; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -public class ITestReporterWithFilter +public class ITestReporterWithFilter extends AbstractSpecificationFileBasedTest { public static final String SPECIFICATION = String.join(System.lineSeparator(), // "`feat~a~1`", // @@ -67,11 +66,7 @@ public class ITestReporterWithFilter @Before public void before() throws IOException { - final File specification = this.tempFolder.newFile("spec.md"); - final PrintWriter writer = new PrintWriter(specification); - writer.print(SPECIFICATION); - writer.flush(); - writer.close(); + writeTextFile(this.tempFolder.newFile("spec.md"), SPECIFICATION); this.reporter = new ReportMode(); this.reporter.addInputs(this.tempFolder.getRoot().toPath()); } @@ -111,4 +106,4 @@ public void testFilterWithAtLeastOneMatchingTagOrNoTags() assertThat(filteredIds, containsInAnyOrder("feat~a~1", "req~b~2", "dsn~c~3", "impl~d~4")); } -} +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java new file mode 100644 index 00000000..6e3a284b --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java @@ -0,0 +1,39 @@ +package org.itsallcode.openfasttrace.testutil; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; + +public class AbstractSpecificationFileBasedTest +{ + + protected void writeTextFile(final File file, final String content) throws IOException + { + final PrintWriter writer = new PrintWriter(file); + writer.print(content); + writer.close(); + } + +} From 77e1848791d060f364c44bc55dbcdd9fd75df80e Mon Sep 17 00:00:00 2001 From: redcatbear Date: Tue, 10 Jul 2018 22:03:56 +0200 Subject: [PATCH 15/60] #145: Updated logo Task-Url: https://github.com/itsallcode/openfasttrace/issues/145 --- src/main/resources/openfasttrace_logo.png | Bin 6650 -> 35905 bytes src/main/resources/openfasttrace_logo.svg | 38 +++++++++++++--------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/main/resources/openfasttrace_logo.png b/src/main/resources/openfasttrace_logo.png index 559561707e44d17aaaeb057ea8c7af1fd3bf1721..173953c38c72e1e049c264412ab5fc89c5aeae35 100644 GIT binary patch literal 35905 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 literal 6650 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 JZ`5xF{2!NEcn1Ig diff --git a/src/main/resources/openfasttrace_logo.svg b/src/main/resources/openfasttrace_logo.svg index 64d4ff43..de9325d4 100644 --- a/src/main/resources/openfasttrace_logo.svg +++ b/src/main/resources/openfasttrace_logo.svg @@ -50,6 +50,7 @@ image/svg+xml + @@ -69,7 +70,7 @@ id="namedview22" showgrid="false" inkscape:zoom="0.42331562" - inkscape:cx="83.861777" + inkscape:cx="-316.54868" inkscape:cy="158.4" inkscape:window-x="67" inkscape:window-y="27" @@ -77,30 +78,37 @@ inkscape:current-layer="svg20" /> + style="fill:#58c8fd;fill-opacity:1;stroke:#0a5ddd;stroke-width:111;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + points="4015,6377 3307,5433 4251,3543 6141,3543 6614,4488 5669,6377 " + transform="matrix(1.090922,0,0,1.2645031,-737.28966,-1311.9354)" /> + style="fill:#ffffff;stroke:#0a5ddd;stroke-width:111;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + points="11811,3543 10866,3543 11574,4960 10866,6377 11811,6377 12519,4960 " + transform="matrix(1.090922,0,0,1.2645031,-737.28966,-1311.9354)" /> + style="fill:#58c8fd;fill-opacity:1;stroke:#0a5ddd;stroke-width:111;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + points="8503,4488 9448,4488 8976,3543 7086,3543 5669,6377 6614,6377 7086,5433 8031,5433 " + transform="matrix(1.090922,0,0,1.2645031,-737.28966,-1311.9354)" /> + style="fill:none;stroke:#0a5ddd;stroke-width:111;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + points="7559,4488 8503,4488 " + transform="matrix(1.090922,0,0,1.2645031,-737.28966,-1311.9354)" /> + style="fill:#ffffff;fill-opacity:1;stroke:#0a5ddd;stroke-width:111;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + points="4251,5433 5196,5433 5669,4488 4724,4488 " + transform="matrix(1.090922,0,0,1.2645031,-737.28966,-1311.9354)" /> + style="fill:#58c8fd;fill-opacity:1;stroke:#0a5ddd;stroke-width:111;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + points="9448,6377 8503,6377 9448,4488 8976,3543 10866,3543 11338,4488 10393,4488 " + transform="matrix(1.090922,0,0,1.2645031,-737.28966,-1311.9354)" /> + style="fill:#ffffff;stroke:#0a5ddd;stroke-width:111;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + points="12755,3543 11811,3543 12519,4960 11811,6377 12755,6377 13464,4960 " + transform="matrix(1.090922,0,0,1.2645031,-737.28966,-1311.9354)" /> From 8f047f338fb83a1fd696de2cd4851de851e277f8 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Tue, 10 Jul 2018 22:42:53 +0200 Subject: [PATCH 16/60] #145: Improved test coverage. Task-Url: https://github.com/itsallcode/openfasttrace/issues/145 --- .../openfasttrace/cli/ITestCliWithFilter.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java index 7ff68361..c8aa9f1c 100644 --- a/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java @@ -69,6 +69,24 @@ public void before() throws IOException this.exit.expectSystemExitWithStatus(0); } + // [itest->dsn~filtering-by-tags-during-import~1] + @Test + public void testWithoutFilter() + { + this.exit.checkAssertionAfterwards(new Assertion() + { + @Override + public void checkAssertion() + { + final String stdOut = ITestCliWithFilter.this.systemOutRule.getLog(); + assertThat(stdOut, containsString("a<")); + assertThat(stdOut, containsString("b<")); + assertThat(stdOut, containsString("c<")); + } + }); + runWithArguments("convert", this.specFile.toString()); + } + // [itest->dsn~filtering-by-tags-during-import~1] @Test public void testFilterWithAtLeastOneMatchingTag() @@ -92,6 +110,22 @@ private void runWithArguments(final String... args) CliStarter.main(args); } + // [itest->dsn~filtering-by-tags-during-import~1] + @Test + public void testFilterWithEmptyTagListFiltersOutEverything() + { + this.exit.checkAssertionAfterwards(new Assertion() + { + @Override + public void checkAssertion() + { + final String stdOut = ITestCliWithFilter.this.systemOutRule.getLog(); + assertThat(stdOut, not(containsString(""))); + } + }); + runWithArguments("convert", "-t", "", this.specFile.toString()); + } + // [itest->dsn~filtering-by-tags-or-no-tags-during-import~1] @Test public void testFilterWithAtLeastOneMatchingTagOrNoTags() From 01c109d3b50c7efa81c475356fa7b069855a39f9 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Wed, 11 Jul 2018 20:12:22 +0200 Subject: [PATCH 17/60] #145: Added release letter entry Task-Url: https://github.com/itsallcode/openfasttrace/issues/145 --- doc/releases/oft_release_letter_1.1.0.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 doc/releases/oft_release_letter_1.1.0.md diff --git a/doc/releases/oft_release_letter_1.1.0.md b/doc/releases/oft_release_letter_1.1.0.md new file mode 100644 index 00000000..b2c1f91d --- /dev/null +++ b/doc/releases/oft_release_letter_1.1.0.md @@ -0,0 +1,12 @@ +# OFT Release Letter for Version 1.1.0 + +Release date: + +##### New Features +* Switch for keeping specification items without tags when using tag filter ([#145](https://github.com/itsallcode/openfasttrace/issues/145)) + +##### Bugfixes +* Tags were not imported in some cases from Markdown specification items ([#145](https://github.com/itsallcode/openfasttrace/issues/145)) + +##### Know Issues +* HTML report still in very early demonstrator phase - not production-ready, use plain text report instead. \ No newline at end of file From d4eb1dc26e6d8ea6238091fd017554f2a8ab6b70 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 14 Jul 2018 12:11:54 +0200 Subject: [PATCH 18/60] #156: Capitalize Maven Central --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8cefb446..04e8666a 100644 --- a/README.md +++ b/README.md @@ -180,5 +180,5 @@ mvn -DwithHistory org.pitest:pitest-maven:mutationCoverage 1. Sign in at [bintray.com](https://bintray.com) 1. Go to the [bintray project page](https://bintray.com/itsallcode/itsallcode/openfasttrace) 1. There should be a notice saying "You have 6 unpublished item(s) for this package". Click the "Publish" link. Binaries will be available for download at [jcenter](https://jcenter.bintray.com/org/itsallcode/openfasttrace/) -1. Publish to maven central by clicking the "Sync" button at https://bintray.com/itsallcode/itsallcode/openfasttrace#central. After some time the new version will appear at https://repo1.maven.org/maven2/org/itsallcode/openfasttrace/. +1. Publish to Maven Central by clicking the "Sync" button at https://bintray.com/itsallcode/itsallcode/openfasttrace#central. After some time the new version will appear at https://repo1.maven.org/maven2/org/itsallcode/openfasttrace/. From 368354c9bc54222041944dd1c05986c91f12a8b9 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 14 Jul 2018 12:14:06 +0200 Subject: [PATCH 19/60] Remove unused class --- .../testutil/log/LogHandlerRule.java | 112 ------------------ 1 file changed, 112 deletions(-) delete mode 100644 src/test/java/org/itsallcode/openfasttrace/testutil/log/LogHandlerRule.java diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/log/LogHandlerRule.java b/src/test/java/org/itsallcode/openfasttrace/testutil/log/LogHandlerRule.java deleted file mode 100644 index d980dd47..00000000 --- a/src/test/java/org/itsallcode/openfasttrace/testutil/log/LogHandlerRule.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.itsallcode.openfasttrace.testutil.log; - -/*- - * #%L - * OpenFastTrace - * %% - * Copyright (C) 2016 - 2018 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ -import java.util.logging.*; - -import org.junit.rules.ExternalResource; -import org.junit.rules.TestRule; - -/** - * This junit {@link TestRule} sets a temporary log level and a - * {@link NoOpLoggingHandler} during tests and restores the original state after - * the test. This allows you to run the tests with all log messages but without - * the overhead of spamming the log. - */ -public class LogHandlerRule extends ExternalResource -{ - private static Logger LOG = Logger.getLogger(LogHandlerRule.class.getName()); - private final Logger rootLogger; - private final Handler loggingHandler; - private final Level logLevel; - private Level originalLogLevel; - - private LogHandlerRule(final Handler loggingHandler, final Level logLevel) - { - this.logLevel = logLevel; - this.rootLogger = getRootLogger(); - this.loggingHandler = loggingHandler; - } - - private static Logger getRootLogger() - { - return LogManager.getLogManager().getLogger(""); - } - - /** - * Creates a new {@link LogHandlerRule} that uses log level - * {@link Level#ALL}. - */ - public static LogHandlerRule withNoOpHandler() - { - final NoOpLoggingHandler handler = new NoOpLoggingHandler(); - return new LogHandlerRule(handler, Level.ALL); - } - - @Override - protected void before() - { - installHandler(); - configureLogLevel(); - } - - private void installHandler() - { - LOG.finest(() -> "Installing logging handler " + this.loggingHandler); - this.rootLogger.addHandler(this.loggingHandler); - } - - private void configureLogLevel() - { - this.originalLogLevel = this.rootLogger.getLevel(); - LOG.finest(() -> "Configure log level " + this.logLevel + ", original level was " - + this.originalLogLevel); - this.rootLogger.setLevel(this.logLevel); - } - - @Override - protected void after() - { - restoreLogLevel(); - uninstallHandler(); - } - - private void restoreLogLevel() - { - LOG.finest(() -> "Restore original log level " + this.originalLogLevel); - this.rootLogger.setLevel(this.originalLogLevel); - } - - private void uninstallHandler() - { - final Handler[] handlers = this.rootLogger.getHandlers(); - for (final Handler handler : handlers) - { - if (handler == this.loggingHandler) - { - LOG.finest(() -> "Uninstalling logging handler " + this.loggingHandler); - this.rootLogger.removeHandler(handler); - } - } - } - -} From 12d9540d183ee34c4fbd5a4829dd0e9e38764129 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 14 Jul 2018 12:16:17 +0200 Subject: [PATCH 20/60] Fix review findings --- .../openfasttrace/testutil/log/NoOpLoggingHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/log/NoOpLoggingHandler.java b/src/test/java/org/itsallcode/openfasttrace/testutil/log/NoOpLoggingHandler.java index 4193461e..8902e74f 100644 --- a/src/test/java/org/itsallcode/openfasttrace/testutil/log/NoOpLoggingHandler.java +++ b/src/test/java/org/itsallcode/openfasttrace/testutil/log/NoOpLoggingHandler.java @@ -31,7 +31,6 @@ */ public class NoOpLoggingHandler extends Handler { - public NoOpLoggingHandler() { } @@ -39,18 +38,18 @@ public NoOpLoggingHandler() @Override public void publish(final LogRecord record) { - // empty + // empty on purpose } @Override public void flush() { - // empty + // empty on purpose } @Override public void close() { - // empty + // empty on purpose } } From 80a6c110a3654e6b632ba22112c3953b0b275c14 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sat, 14 Jul 2018 12:46:55 +0200 Subject: [PATCH 21/60] test(#145): Refactored tests and added missing test case for single letter setter. Task-Url: https://github.com/itsallcode/openfasttrace/issues/145 --- doc/releases/oft_release_letter_1.1.0.md | 12 ---- src/main/resources/openfasttrace_logo.svg | 6 +- .../openfasttrace/cli/ITestCliWithFilter.java | 57 ++++++------------- .../openfasttrace/cli/TestCliArguments.java | 31 ++++++++-- 4 files changed, 48 insertions(+), 58 deletions(-) delete mode 100644 doc/releases/oft_release_letter_1.1.0.md diff --git a/doc/releases/oft_release_letter_1.1.0.md b/doc/releases/oft_release_letter_1.1.0.md deleted file mode 100644 index b2c1f91d..00000000 --- a/doc/releases/oft_release_letter_1.1.0.md +++ /dev/null @@ -1,12 +0,0 @@ -# OFT Release Letter for Version 1.1.0 - -Release date: - -##### New Features -* Switch for keeping specification items without tags when using tag filter ([#145](https://github.com/itsallcode/openfasttrace/issues/145)) - -##### Bugfixes -* Tags were not imported in some cases from Markdown specification items ([#145](https://github.com/itsallcode/openfasttrace/issues/145)) - -##### Know Issues -* HTML report still in very early demonstrator phase - not production-ready, use plain text report instead. \ No newline at end of file diff --git a/src/main/resources/openfasttrace_logo.svg b/src/main/resources/openfasttrace_logo.svg index de9325d4..9ef453eb 100644 --- a/src/main/resources/openfasttrace_logo.svg +++ b/src/main/resources/openfasttrace_logo.svg @@ -41,7 +41,10 @@ version="1.1" id="svg20" sodipodi:docname="openfasttrace_logo.svg" - inkscape:version="0.92.3 (2405546, 2018-03-11)"> + inkscape:version="0.92.3 (2405546, 2018-03-11)" + inkscape:export-filename="/home/sebastian/git/openfasttrace/src/main/resources/openfasttrace_logo.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> @@ -50,7 +53,6 @@ image/svg+xml - diff --git a/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java index c8aa9f1c..7ba37ac5 100644 --- a/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java @@ -34,7 +34,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.contrib.java.lang.system.Assertion; import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.junit.contrib.java.lang.system.SystemOutRule; import org.junit.rules.TemporaryFolder; @@ -73,16 +72,11 @@ public void before() throws IOException @Test public void testWithoutFilter() { - this.exit.checkAssertionAfterwards(new Assertion() - { - @Override - public void checkAssertion() - { - final String stdOut = ITestCliWithFilter.this.systemOutRule.getLog(); - assertThat(stdOut, containsString("a<")); - assertThat(stdOut, containsString("b<")); - assertThat(stdOut, containsString("c<")); - } + this.exit.checkAssertionAfterwards(() -> { + final String stdOut = this.systemOutRule.getLog(); + assertThat(stdOut, containsString("a<")); + assertThat(stdOut, containsString("b<")); + assertThat(stdOut, containsString("c<")); }); runWithArguments("convert", this.specFile.toString()); } @@ -91,16 +85,11 @@ public void checkAssertion() @Test public void testFilterWithAtLeastOneMatchingTag() { - this.exit.checkAssertionAfterwards(new Assertion() - { - @Override - public void checkAssertion() - { - final String stdOut = ITestCliWithFilter.this.systemOutRule.getLog(); - assertThat(stdOut, not(containsString("a<"))); - assertThat(stdOut, containsString("b<")); - assertThat(stdOut, not(containsString("c<"))); - } + this.exit.checkAssertionAfterwards(() -> { + final String stdOut = this.systemOutRule.getLog(); + assertThat(stdOut, not(containsString("a<"))); + assertThat(stdOut, containsString("b<")); + assertThat(stdOut, not(containsString("c<"))); }); runWithArguments("convert", "-t", "tag1", this.specFile.toString()); } @@ -114,14 +103,9 @@ private void runWithArguments(final String... args) @Test public void testFilterWithEmptyTagListFiltersOutEverything() { - this.exit.checkAssertionAfterwards(new Assertion() - { - @Override - public void checkAssertion() - { - final String stdOut = ITestCliWithFilter.this.systemOutRule.getLog(); - assertThat(stdOut, not(containsString(""))); - } + this.exit.checkAssertionAfterwards(() -> { + final String stdOut = this.systemOutRule.getLog(); + assertThat(stdOut, not(containsString(""))); }); runWithArguments("convert", "-t", "", this.specFile.toString()); } @@ -130,16 +114,11 @@ public void checkAssertion() @Test public void testFilterWithAtLeastOneMatchingTagOrNoTags() { - this.exit.checkAssertionAfterwards(new Assertion() - { - @Override - public void checkAssertion() - { - final String stdOut = ITestCliWithFilter.this.systemOutRule.getLog(); - assertThat(stdOut, containsString("a<")); - assertThat(stdOut, containsString("b<")); - assertThat(stdOut, not(containsString("c<"))); - } + this.exit.checkAssertionAfterwards(() -> { + final String stdOut = this.systemOutRule.getLog(); + assertThat(stdOut, containsString("a<")); + assertThat(stdOut, containsString("b<")); + assertThat(stdOut, not(containsString("c<"))); }); runWithArguments("convert", "-t", "_,tag1", this.specFile.toString()); } diff --git a/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java b/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java index 10462a61..46c9661d 100644 --- a/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java +++ b/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java @@ -159,44 +159,65 @@ public void testSetN() assertThat(AFTER_SETTER, this.arguments.getNewline(), equalTo(value)); } + // [utest->dsn~filtering-by-artifact-types-during-import~1] + @Test + public void testWantedArtifactTypesEmptyByDefault() + { + assertThat(BEFORE_SETTER, this.arguments.getWantedArtifactTypes(), emptyIterable()); + } + // [utest->dsn~filtering-by-artifact-types-during-import~1] @Test public void testSetIngnoreArtifactTypes() { final String value = "impl,utest"; - assertThat(BEFORE_SETTER, this.arguments.getWantedArtifactTypes(), emptyIterable()); this.arguments.setWantedArtifactTypes(value); assertThat(AFTER_SETTER, this.arguments.getWantedArtifactTypes(), containsInAnyOrder("impl", "utest")); } + // [utest->dsn~filtering-by-artifact-types-during-import~1] @Test - public void testSetI() + public void testSetA() { final String value = "impl,utest"; - assertThat(BEFORE_SETTER, this.arguments.getWantedArtifactTypes(), emptyIterable()); this.arguments.setA(value); assertThat(AFTER_SETTER, this.arguments.getWantedArtifactTypes(), containsInAnyOrder("impl", "utest")); } + // [utest->dsn~filtering-by-tags-during-import~1] + @Test + public void testWantedTagsEmptyByDefault() + { + assertThat(BEFORE_SETTER, this.arguments.getWantedTags(), emptyIterable()); + } + // [utest->dsn~filtering-by-tags-during-import~1] @Test public void testSetWantedTags() { final String value = "client,server"; - assertThat(BEFORE_SETTER, this.arguments.getWantedTags(), emptyIterable()); this.arguments.setWantedTags(value); assertThat(AFTER_SETTER, this.arguments.getWantedTags(), containsInAnyOrder("client", "server")); } + // [utest->dsn~filtering-by-tags-during-import~1] + @Test + public void testSetd() + { + final String value = "client,server"; + this.arguments.setT(value); + assertThat(AFTER_SETTER, this.arguments.getWantedTags(), + containsInAnyOrder("client", "server")); + } + // [utest->dsn~filtering-by-tags-or-no-tags-during-import~1] @Test public void testSetWantedTagsIncludingNone() { final String value = "_,client,server"; - assertThat(BEFORE_SETTER, this.arguments.getWantedTags(), emptyIterable()); this.arguments.setWantedTags(value); assertThat(AFTER_SETTER, this.arguments.getWantedTags(), containsInAnyOrder("_", "client", "server")); From 4e59a12ed89a8bb7f392d67ebe0881bfdce379f5 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sat, 14 Jul 2018 12:50:43 +0200 Subject: [PATCH 22/60] test(#145): Explicitly set charset to UTF-8 in PrintWriter for AbstractSpecificationFileBasedTest. Task-Url: https://github.com/itsallcode/openfasttrace/issues/145 --- .../testutil/AbstractSpecificationFileBasedTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java index 6e3a284b..e43bd139 100644 --- a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java @@ -25,15 +25,14 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; public class AbstractSpecificationFileBasedTest { - protected void writeTextFile(final File file, final String content) throws IOException { - final PrintWriter writer = new PrintWriter(file); + final PrintWriter writer = new PrintWriter(file, StandardCharsets.UTF_8.toString()); writer.print(content); writer.close(); } - } From 2dbec404e14cc273a7f84f7b6d31e6c27b63d2a5 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sat, 14 Jul 2018 13:10:25 +0200 Subject: [PATCH 23/60] Incremented version number. --- README.md | 6 +++--- pom.xml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 04e8666a..0592843d 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Sonarcloud status: Download the executable jar at [jcenter](https://jcenter.bintray.com/org/itsallcode/openfasttrace/): -* [openfasttrace-1.0.0.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.0.0/openfasttrace-1.0.0.jar) +* [openfasttrace-1.1.0.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.1.0/openfasttrace-1.1.0.jar) ### Maven @@ -51,7 +51,7 @@ To use OpenFastTrace as a dependency in your maven project add this to your `pom org.itsallcode openfasttrace - 1.0.0 + 1.1.0 compile @@ -66,7 +66,7 @@ repositories { jcenter() } dependencies { - compile "org.itsallcode:openfasttrace:1.0.0" + compile "org.itsallcode:openfasttrace:1.1.0" } ``` diff --git a/pom.xml b/pom.xml index 3b22a648..15205c27 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.itsallcode openfasttrace - 1.0.2 + 1.1.0 OpenFastTrace Free requirement tracking suite https://github.com/itsallcode/openfasttrace @@ -318,4 +318,4 @@ - \ No newline at end of file + From 96da2f84128be27ea63be0a80f5398bd1462cb1a Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 15 Jul 2018 11:11:58 +0200 Subject: [PATCH 24/60] doc(): Add Maven Central badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0592843d..f9567f2f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ You can learn more about requirement tracing and how to use OpenFastTrace in the [![codecov](https://codecov.io/gh/itsallcode/openfasttrace/branch/develop/graph/badge.svg)](https://codecov.io/gh/itsallcode/openfasttrace) [![Coverity Scan Build Status](https://scan.coverity.com/projects/14936/badge.svg)](https://scan.coverity.com/projects/itsallcode-openfasttrace) [![Download](https://api.bintray.com/packages/itsallcode/itsallcode/openfasttrace/images/download.svg)](https://bintray.com/itsallcode/itsallcode/openfasttrace/_latestVersion) +[![Maven Central](https://img.shields.io/maven-central/v/org.itsallcode/openfasttrace.svg?label=Maven%20Central)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.itsallcode%22%20a%3A%22openfasttrace%22) Sonarcloud status: From b67f093ed043d2ffa655e3d6422d898606b5dec0 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sun, 15 Jul 2018 11:25:52 +0200 Subject: [PATCH 25/60] doc(): Fix typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b9b1fe7..10bb136d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ Thank you for your interest in helping us to make OpenFastTrace (OFT) better! # Goal of This Document -This document aims at answering all the questions potential contributers to OFT might have before feeling ready to get started. +This document aims at answering all the questions potential contributors to OFT might have before feeling ready to get started. # What This Document is not If you are looking for general information about what OpenFastTrace is, please make sure to check out the [ReadMe](./README.md) that comes with the project. From a0b779b32950c22e99e8c3fd80c53bcbfd066c0a Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sat, 21 Jul 2018 19:14:16 +0200 Subject: [PATCH 26/60] feat(#163): Inline CSS stylesheet into HTML report Task-Url: https://github.com/itsallcode/openfasttrace/issues/163 --- doc/design.md | 11 ++ doc/system_requirements.md | 28 +++++ doc/user_guide.md | 9 ++ pom.xml | 2 + .../report/view/html/HtmlView.java | 67 ++++++++++- .../oft_tracing_report.css => css/report.css} | 26 +--- src/main/resources/openfasttrace_logo.txt | 5 +- .../report-templates/tracing_report_list.html | 111 ------------------ .../tracing_report_list_with_divs.html | 91 -------------- .../openfasttrace/cli/ITestCliWithFilter.java | 9 +- .../mode/ITestReporterWithFilter.java | 4 +- .../html/TestHtmlReportCssInlining.java | 69 +++++++++++ .../view/html/AbstractTestHtmlRenderer.java | 11 ++ .../report/view/html/TestHtmlView.java | 4 +- ...edTest.java => AbstractFileBasedTest.java} | 12 +- 15 files changed, 215 insertions(+), 244 deletions(-) rename src/main/resources/{report-templates/oft_tracing_report.css => css/report.css} (65%) delete mode 100644 src/main/resources/report-templates/tracing_report_list.html delete mode 100644 src/main/resources/report-templates/tracing_report_list_with_divs.html create mode 100644 src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java rename src/test/java/org/itsallcode/openfasttrace/testutil/{AbstractSpecificationFileBasedTest.java => AbstractFileBasedTest.java} (80%) diff --git a/doc/design.md b/doc/design.md index ff99dd9b..84d73c40 100644 --- a/doc/design.md +++ b/doc/design.md @@ -322,6 +322,17 @@ Covers: Needs: impl, utest +#### HTML Report Inlines CSS +`dsn~reporting.html.inline_css~1` + +OFT inlines the cascading style sheet (CSS) into the HTML report. + +Covers: + +* `req~reporting.html.single_file~1` + +Needs: impl, itest + ## Requirement Format Conversion ### ReqM2 Export diff --git a/doc/system_requirements.md b/doc/system_requirements.md index 0fda8950..8dcb0c12 100644 --- a/doc/system_requirements.md +++ b/doc/system_requirements.md @@ -130,6 +130,17 @@ This can be read directly as console output or with any text editor. Needs: req +#### HTML Report +`feat~html-report~1` + +OFT produces a tracing report in Hypertext markup language (HTML). + +Rationale: + +This report type is more optically appealing than the plain text report and still widely supported on all platforms. + +Needs: req + ### User Interface #### Command Line Interface @@ -498,6 +509,23 @@ Covers: Needs: dsn +#### HTML Report + +##### HTML Report is a Single File +`req~reporting.html.single_file~1` + +OFT creates the HTML Report as a single file. + +Rationale: + +It makes exchanging reports with other people easier if everything is contained in a single file. + +Covers: + +* [feat~html-report~1](#html-report) + +Needs: dsn + ### Requirement Format Conversion OFT supports conversion from one requirement format into another for example from Markdown to ReqM2. diff --git a/doc/user_guide.md b/doc/user_guide.md index 28d5d51c..7e2587db 100644 --- a/doc/user_guide.md +++ b/doc/user_guide.md @@ -327,6 +327,14 @@ By default this will produce a plain text trace that displays a details of all d See also: * [Tracing Options](#tracing-options) for controlling the tracing output +### HTML Tracing Reports + +While plain text reports are perfect for debugging you tracing chain, sometimes you need reports that are more optically appealing. This is usually true if you have to show reports to management or to quality assessors who usually focus on summaries and statistics rather than detail results. In this case you can tell OFT to create reports in HTML format by adding the `-o html` switch. + +```sh +oft trace -o html +``` + ## Reference ### OFT Command Line @@ -360,6 +368,7 @@ The format of the report. One of: * `plain` +* `html` Defaults to `plain`. diff --git a/pom.xml b/pom.xml index 15205c27..fe8346c5 100644 --- a/pom.xml +++ b/pom.xml @@ -197,6 +197,8 @@ test/resources/specobject/*.xml + **/*.css + **/*.html true true diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java index ef892186..240a86bc 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java @@ -1,5 +1,8 @@ package org.itsallcode.openfasttrace.report.view.html; +import java.io.IOException; +import java.io.InputStream; + /*- * #%L * OpenFastTrace @@ -24,6 +27,7 @@ import java.io.PrintStream; +import org.itsallcode.openfasttrace.report.ReportException; import org.itsallcode.openfasttrace.report.view.AbstractViewContainer; import org.itsallcode.openfasttrace.report.view.Viewable; @@ -34,19 +38,42 @@ public class HtmlView extends AbstractViewContainer implements Viewable { private final String title; private final PrintStream stream; + private final boolean inlineCSS; + private static final String REPORT_CSS_FILE = "/css/report.css"; /** * Create a new instance of type {@link HtmlView}. * + * @param stream + * the stream to write to + * * @param id * the view ID * @param title * the view title */ - public HtmlView(final PrintStream stream, final String id, final String title) + public HtmlView(final PrintStream stream, final String id, final String title, + final boolean inlineCSS) { this.stream = stream; this.title = title; + this.inlineCSS = inlineCSS; + } + + /** + * Create a new instance of type {@link HtmlView}. + * + * @param stream + * the stream to write to + * + * @param id + * the view ID + * @param title + * the view title + */ + public HtmlView(final PrintStream stream, final String id, final String title) + { + this(stream, id, title, true); } @Override @@ -55,9 +82,8 @@ public void renderBeforeChildren(final int level) this.stream.println(""); this.stream.println(""); this.stream.println(" "); - this.stream.println( - " "); this.stream.println(" "); + inlineCSS(); this.stream.print(" "); this.stream.print(this.title); this.stream.println(""); @@ -65,6 +91,41 @@ public void renderBeforeChildren(final int level) this.stream.println(" "); } + // [impl->dsn~reporting.html.inline_css~1] + private void inlineCSS() + { + if (this.inlineCSS) + { + this.stream.println(" "); + } + } + + private void copyCSSContent(final InputStream css) throws ReportException + { + final byte[] buffer = new byte[4096]; + int n; + try + { + while ((n = css.read(buffer)) > 0) + { + this.stream.write(buffer, 0, n); + } + } + catch (final IOException e) + { + throw new ReportException("Unable to copy CSS content \"" + REPORT_CSS_FILE + + "\" trying to generate HTML view.", e); + } + } + @Override public void renderAfterChildren(final int level) { diff --git a/src/main/resources/report-templates/oft_tracing_report.css b/src/main/resources/css/report.css similarity index 65% rename from src/main/resources/report-templates/oft_tracing_report.css rename to src/main/resources/css/report.css index 7a874223..a10dd10b 100644 --- a/src/main/resources/report-templates/oft_tracing_report.css +++ b/src/main/resources/css/report.css @@ -1,27 +1,5 @@ -/*- - * #%L - * OpenFastTrace - * %% - * Copyright (C) 2016 - 2018 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - * { - font-family: helvetica, arial + font-family: helvetica, arial; } nav { @@ -140,4 +118,4 @@ summary .title { text-align: right; border-top: 1px solid lightgrey; font-family: courier; -} \ No newline at end of file +} diff --git a/src/main/resources/openfasttrace_logo.txt b/src/main/resources/openfasttrace_logo.txt index 340d527b..6861b677 100644 --- a/src/main/resources/openfasttrace_logo.txt +++ b/src/main/resources/openfasttrace_logo.txt @@ -1,5 +1,4 @@ ___ ________ _ / _ |/ __| _/\\\ - / // / _/ / / \\\ - \___/_/ /_/ /// -________________/// + / // / _/ / / ))) + \___/_/ /_/ /// \ No newline at end of file diff --git a/src/main/resources/report-templates/tracing_report_list.html b/src/main/resources/report-templates/tracing_report_list.html deleted file mode 100644 index c7c16b50..00000000 --- a/src/main/resources/report-templates/tracing_report_list.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - -Specification Item list - OFT 0.5.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StatusCoveredArtifactTitle / IDRev.InDupl.OutNeeds
ΔΔ
T
okdeepdsnTitle of a design item A103002impl, utest, itest
not okpartiallydsnTitle of a design item B123002impl, uman, utest, itest
- - diff --git a/src/main/resources/report-templates/tracing_report_list_with_divs.html b/src/main/resources/report-templates/tracing_report_list_with_divs.html deleted file mode 100644 index 3192a143..00000000 --- a/src/main/resources/report-templates/tracing_report_list_with_divs.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - Specification Item list - OFT 0.5.1 - - - - -
-
-

T

-
-
- - ✅ Title of a design item A, rev. 1, dsn - -

dsn~design-item-a~1

-

This is the description of the design item A

-
Needs: impl, itest, utest
-
Out: 1 total
- -
In: 3 total
- -
-
-
-
- - ❎ Title of a design item B, rev. 2, dsn (covered partially, 3 duplicates, 2 defect links) - -

This is the description of the design item B

-
Rationale:
-

Here we have the rationale, that explains why the requirement is needed.

-
Comment:
-

A comment further explaining the requirement without being normative.

-
- Needs: impl, - itest - , - uman - , utest -
-
Out: 1 total
- -
In: 4 total, 2 defect
- -

Tags: Tag A Tag B -

-
-
-
- - diff --git a/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java index 7ba37ac5..0d5344c0 100644 --- a/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/cli/ITestCliWithFilter.java @@ -30,7 +30,7 @@ import java.io.File; import java.io.IOException; -import org.itsallcode.openfasttrace.testutil.AbstractSpecificationFileBasedTest; +import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -38,7 +38,7 @@ import org.junit.contrib.java.lang.system.SystemOutRule; import org.junit.rules.TemporaryFolder; -public class ITestCliWithFilter extends AbstractSpecificationFileBasedTest +public class ITestCliWithFilter extends AbstractFileBasedTest { public static final String SPECIFICATION = String.join(System.lineSeparator(), // "`feat~a~1`", // @@ -94,11 +94,6 @@ public void testFilterWithAtLeastOneMatchingTag() runWithArguments("convert", "-t", "tag1", this.specFile.toString()); } - private void runWithArguments(final String... args) - { - CliStarter.main(args); - } - // [itest->dsn~filtering-by-tags-during-import~1] @Test public void testFilterWithEmptyTagListFiltersOutEverything() diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java index d8c97d07..0c5ac6f5 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java @@ -34,13 +34,13 @@ import org.itsallcode.openfasttrace.FilterSettings; import org.itsallcode.openfasttrace.Reporter; import org.itsallcode.openfasttrace.core.Trace; -import org.itsallcode.openfasttrace.testutil.AbstractSpecificationFileBasedTest; +import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -public class ITestReporterWithFilter extends AbstractSpecificationFileBasedTest +public class ITestReporterWithFilter extends AbstractFileBasedTest { public static final String SPECIFICATION = String.join(System.lineSeparator(), // "`feat~a~1`", // diff --git a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java new file mode 100644 index 00000000..8d4ad733 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java @@ -0,0 +1,69 @@ +package org.itsallcode.openfasttrace.report.html; + +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertThat; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import java.io.File; +import java.io.IOException; + +import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.ExpectedSystemExit; +import org.junit.contrib.java.lang.system.SystemOutRule; +import org.junit.rules.TemporaryFolder; + +public class TestHtmlReportCssInlining extends AbstractFileBasedTest +{ + private static final String CSS = "* {\n font-family: helvetica, arial;\n}"; + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + @Rule + public final SystemOutRule systemOutRule = new SystemOutRule().enableLog(); + @Rule + public final ExpectedSystemExit exit = ExpectedSystemExit.none(); + private File specFile; + + @Before + public void before() throws IOException + { + this.specFile = this.tempFolder.newFile("spec.md"); + writeTextFile(this.specFile, "Dummy content"); + this.exit.expectSystemExitWithStatus(0); + } + + // [itest->dsn~reporting.html.inline_css~1] + @Test + public void testHtmlReportContainsInlineCSS() + { + this.exit.checkAssertionAfterwards(() -> { + final String stdOut = this.systemOutRule.getLog(); + assertThat(stdOut, containsString(CSS)); + }); + runWithArguments("trace", "-o", "html", this.specFile.toString()); + } +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/AbstractTestHtmlRenderer.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/AbstractTestHtmlRenderer.java index eea55d44..8d994d7d 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/view/html/AbstractTestHtmlRenderer.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/AbstractTestHtmlRenderer.java @@ -27,6 +27,7 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStream; +import java.util.regex.Pattern; import org.itsallcode.openfasttrace.report.view.ViewFactory; import org.junit.Before; @@ -47,4 +48,14 @@ protected void assertOutputLines(final String... lines) { assertThat(this.outputStream.toString(), matchesAllLines(lines)); } + + protected void assertOutputLinesWithoutCSS(final String... lines) + { + final String html = this.outputStream.toString(); + final String htmlWithoutCSS = Pattern // + .compile("", Pattern.DOTALL) // + .matcher(html) // + .replaceAll(""); + assertThat(htmlWithoutCSS, matchesAllLines(lines)); + } } diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlView.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlView.java index 258c9d8c..b2465c29 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlView.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlView.java @@ -43,12 +43,12 @@ public void testRender() { final Viewable view = this.factory.createView(ID, TITLE); view.render(1); - assertOutputLines(// + assertOutputLinesWithoutCSS(// "", // "", // " ", // - " ", // " ", // + " ", // " " + TITLE + "", // " ", // " ", // diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java similarity index 80% rename from src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java rename to src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java index e43bd139..fba40cfc 100644 --- a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractSpecificationFileBasedTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java @@ -27,7 +27,12 @@ import java.io.PrintWriter; import java.nio.charset.StandardCharsets; -public class AbstractSpecificationFileBasedTest +import org.itsallcode.openfasttrace.cli.CliStarter; + +/** + * This class is the base class for integration tests that require input files. + */ +public class AbstractFileBasedTest { protected void writeTextFile(final File file, final String content) throws IOException { @@ -35,4 +40,9 @@ protected void writeTextFile(final File file, final String content) throws IOExc writer.print(content); writer.close(); } + + protected void runWithArguments(final String... args) + { + CliStarter.main(args); + } } From a91838a76999320549b02644acd3437b477d8c45 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sat, 21 Jul 2018 19:46:56 +0200 Subject: [PATCH 27/60] #163: Improved stream handling and test coverage. Task-Url: https://github.com/itsallcode/openfasttrace/issues/163 --- .../openfasttrace/report/view/ViewType.java | 28 ----------- .../report/view/html/HtmlView.java | 47 ++++--------------- 2 files changed, 8 insertions(+), 67 deletions(-) delete mode 100644 src/main/java/org/itsallcode/openfasttrace/report/view/ViewType.java diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/ViewType.java b/src/main/java/org/itsallcode/openfasttrace/report/view/ViewType.java deleted file mode 100644 index eb5042d9..00000000 --- a/src/main/java/org/itsallcode/openfasttrace/report/view/ViewType.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.itsallcode.openfasttrace.report.view; - -/*- - * #%L - * OpenFastTrace - * %% - * Copyright (C) 2016 - 2018 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -public enum ViewType -{ - HTML5 -} diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java index 240a86bc..b9972daf 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java @@ -38,7 +38,6 @@ public class HtmlView extends AbstractViewContainer implements Viewable { private final String title; private final PrintStream stream; - private final boolean inlineCSS; private static final String REPORT_CSS_FILE = "/css/report.css"; /** @@ -52,28 +51,10 @@ public class HtmlView extends AbstractViewContainer implements Viewable * @param title * the view title */ - public HtmlView(final PrintStream stream, final String id, final String title, - final boolean inlineCSS) + public HtmlView(final PrintStream stream, final String id, final String title) { this.stream = stream; this.title = title; - this.inlineCSS = inlineCSS; - } - - /** - * Create a new instance of type {@link HtmlView}. - * - * @param stream - * the stream to write to - * - * @param id - * the view ID - * @param title - * the view title - */ - public HtmlView(final PrintStream stream, final String id, final String title) - { - this(stream, id, title, true); } @Override @@ -83,7 +64,9 @@ public void renderBeforeChildren(final int level) this.stream.println(""); this.stream.println(" "); this.stream.println(" "); + this.stream.println(" "); this.stream.print(" "); this.stream.print(this.title); this.stream.println(""); @@ -94,26 +77,12 @@ public void renderBeforeChildren(final int level) // [impl->dsn~reporting.html.inline_css~1] private void inlineCSS() { - if (this.inlineCSS) - { - this.stream.println(" "); - } - } - - private void copyCSSContent(final InputStream css) throws ReportException - { - final byte[] buffer = new byte[4096]; - int n; - try + try (final InputStream css = getClass().getResourceAsStream(REPORT_CSS_FILE)) { + assert css != null : "Null pointer trying to open CSS stylesheet \"" + REPORT_CSS_FILE + + "\" to generate HTML view."; + final byte[] buffer = new byte[4096]; + int n; while ((n = css.read(buffer)) > 0) { this.stream.write(buffer, 0, n); From 5850af8bf826f0df9af9929ca723dbd6c3e4045b Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sun, 22 Jul 2018 12:22:48 +0200 Subject: [PATCH 28/60] #163: Improved testablility, test coverage and test speed. Task-Url: https://github.com/itsallcode/openfasttrace/issues/163 --- .../openfasttrace/report/html/HtmlReport.java | 14 +++- .../report/view/html/HtmlView.java | 12 ++-- .../report/view/html/HtmlViewFactory.java | 11 +-- .../html/TestHtmlReportCssInlining.java | 71 ++++++++----------- .../view/html/AbstractTestHtmlRenderer.java | 3 +- .../report/view/html/TestHtmlViewFactory.java | 3 +- 6 files changed, 60 insertions(+), 54 deletions(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java b/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java index 18268465..ed3aedba 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java @@ -23,6 +23,7 @@ */ import java.io.OutputStream; +import java.net.URL; import java.util.Comparator; import java.util.List; @@ -38,17 +39,28 @@ public class HtmlReport implements Reportable { private final Trace trace; + private static final String REPORT_CSS_FILE = "/css/report.css"; public HtmlReport(final Trace trace) { this.trace = trace; } + /** + * Get the URL to the CSS stylesheet that is used to lay out the HTML Report + * + * @return the URL of the CSS stylesheet + */ + public static URL getCssUrl() + { + return HtmlReport.class.getResource(REPORT_CSS_FILE); + } + @Override public void renderToStreamWithVerbosityLevel(final OutputStream outputStream, final ReportVerbosity verbosity) { - final ViewFactory factory = HtmlViewFactory.create(outputStream); + final ViewFactory factory = HtmlViewFactory.create(outputStream, getCssUrl()); final ViewableContainer view = factory.createView("", "Specification items by title"); final List items = this.trace.getItems(); items.sort(Comparator.comparing(LinkedSpecificationItem::getTitleWithFallback)); diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java index b9972daf..b3549308 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlView.java @@ -26,6 +26,7 @@ */ import java.io.PrintStream; +import java.net.URL; import org.itsallcode.openfasttrace.report.ReportException; import org.itsallcode.openfasttrace.report.view.AbstractViewContainer; @@ -38,7 +39,7 @@ public class HtmlView extends AbstractViewContainer implements Viewable { private final String title; private final PrintStream stream; - private static final String REPORT_CSS_FILE = "/css/report.css"; + private final URL cssURL; /** * Create a new instance of type {@link HtmlView}. @@ -51,10 +52,11 @@ public class HtmlView extends AbstractViewContainer implements Viewable * @param title * the view title */ - public HtmlView(final PrintStream stream, final String id, final String title) + public HtmlView(final PrintStream stream, final String id, final String title, final URL cssURL) { this.stream = stream; this.title = title; + this.cssURL = cssURL; } @Override @@ -77,10 +79,8 @@ public void renderBeforeChildren(final int level) // [impl->dsn~reporting.html.inline_css~1] private void inlineCSS() { - try (final InputStream css = getClass().getResourceAsStream(REPORT_CSS_FILE)) + try (final InputStream css = this.cssURL.openStream()) { - assert css != null : "Null pointer trying to open CSS stylesheet \"" + REPORT_CSS_FILE - + "\" to generate HTML view."; final byte[] buffer = new byte[4096]; int n; while ((n = css.read(buffer)) > 0) @@ -90,7 +90,7 @@ private void inlineCSS() } catch (final IOException e) { - throw new ReportException("Unable to copy CSS content \"" + REPORT_CSS_FILE + throw new ReportException("Unable to copy CSS content \"" + this.cssURL.toString() + "\" trying to generate HTML view.", e); } } diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlViewFactory.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlViewFactory.java index 9227737f..4340f999 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlViewFactory.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlViewFactory.java @@ -25,6 +25,7 @@ import java.io.OutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; +import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -37,15 +38,17 @@ public class HtmlViewFactory extends AbstractViewFactory { private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + private final URL cssUrl; - HtmlViewFactory(final PrintStream stream) + HtmlViewFactory(final PrintStream stream, final URL cssUrl) { super(stream); + this.cssUrl = cssUrl; } - public static HtmlViewFactory create(final OutputStream stream) + public static HtmlViewFactory create(final OutputStream stream, final URL cssURL) { - return new HtmlViewFactory(createPrintStream(stream, DEFAULT_CHARSET)); + return new HtmlViewFactory(createPrintStream(stream, DEFAULT_CHARSET), cssURL); } private static PrintStream createPrintStream(final OutputStream stream, final Charset charset) @@ -63,7 +66,7 @@ private static PrintStream createPrintStream(final OutputStream stream, final Ch @Override public ViewableContainer createView(final String id, final String title) { - return new HtmlView(this.outputStream, id, title); + return new HtmlView(this.outputStream, id, title, this.cssUrl); } @Override diff --git a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java index 8d4ad733..70db2767 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java @@ -3,67 +3,56 @@ import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertThat; -/*- - * #%L - * OpenFastTrace - * %% - * Copyright (C) 2016 - 2018 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import org.itsallcode.openfasttrace.report.view.ViewableContainer; +import org.itsallcode.openfasttrace.report.view.html.HtmlViewFactory; import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.contrib.java.lang.system.ExpectedSystemExit; import org.junit.contrib.java.lang.system.SystemOutRule; import org.junit.rules.TemporaryFolder; public class TestHtmlReportCssInlining extends AbstractFileBasedTest { - private static final String CSS = "* {\n font-family: helvetica, arial;\n}"; + private static final String CSS = "* { font-family: helvetica; }"; @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); @Rule public final SystemOutRule systemOutRule = new SystemOutRule().enableLog(); - @Rule - public final ExpectedSystemExit exit = ExpectedSystemExit.none(); - private File specFile; - @Before - public void before() throws IOException + // [itest->dsn~reporting.html.inline_css~1] + @Test + public void testHtmlReportContainsInlineCSS() throws IOException { - this.specFile = this.tempFolder.newFile("spec.md"); - writeTextFile(this.specFile, "Dummy content"); - this.exit.expectSystemExitWithStatus(0); + final File cssFile = this.tempFolder.newFile("test.css"); + writeTextFile(cssFile, CSS); + final HtmlViewFactory factory = HtmlViewFactory.create(System.out, cssFile.toURI().toURL()); + final ViewableContainer view = factory.createView("foo", "bar"); + view.render(); + assertThat(this.systemOutRule.getLog(), containsString(CSS)); } - // [itest->dsn~reporting.html.inline_css~1] - @Test - public void testHtmlReportContainsInlineCSS() + @Test(expected = org.itsallcode.openfasttrace.report.ReportException.class) + public void testInliningNonExistentCssThrowsException() throws MalformedURLException + { + final HtmlViewFactory factory = HtmlViewFactory.create(System.out, + new URL("file:///this_file_does_not_exist.css")); + final ViewableContainer view = factory.createView("foo", "bar"); + view.render(); + } + + @Test(expected = org.itsallcode.openfasttrace.report.ReportException.class) + public void testInliningUnreadableCssThrowsException() throws IOException { - this.exit.checkAssertionAfterwards(() -> { - final String stdOut = this.systemOutRule.getLog(); - assertThat(stdOut, containsString(CSS)); - }); - runWithArguments("trace", "-o", "html", this.specFile.toString()); + final File cssFile = this.tempFolder.newFile("test.css"); + cssFile.setReadable(false); + final HtmlViewFactory factory = HtmlViewFactory.create(System.out, cssFile.toURI().toURL()); + final ViewableContainer view = factory.createView("foo", "bar"); + view.render(); } } \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/AbstractTestHtmlRenderer.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/AbstractTestHtmlRenderer.java index 8d994d7d..ef7e8c3d 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/view/html/AbstractTestHtmlRenderer.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/AbstractTestHtmlRenderer.java @@ -29,6 +29,7 @@ import java.io.OutputStream; import java.util.regex.Pattern; +import org.itsallcode.openfasttrace.report.html.HtmlReport; import org.itsallcode.openfasttrace.report.view.ViewFactory; import org.junit.Before; @@ -41,7 +42,7 @@ public class AbstractTestHtmlRenderer public void prepareEachTest() { this.outputStream = new ByteArrayOutputStream(); - this.factory = HtmlViewFactory.create(this.outputStream); + this.factory = HtmlViewFactory.create(this.outputStream, HtmlReport.getCssUrl()); } protected void assertOutputLines(final String... lines) diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlViewFactory.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlViewFactory.java index dda84909..70f4ee07 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlViewFactory.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlViewFactory.java @@ -29,6 +29,7 @@ import java.io.OutputStream; import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; +import org.itsallcode.openfasttrace.report.html.HtmlReport; import org.itsallcode.openfasttrace.report.view.ViewFactory; import org.itsallcode.openfasttrace.report.view.Viewable; import org.junit.Test; @@ -41,7 +42,7 @@ public class TestHtmlViewFactory public void testCreateSpecificationItem() { final OutputStream outputStream = new ByteArrayOutputStream(); - final ViewFactory factory = HtmlViewFactory.create(outputStream); + final ViewFactory factory = HtmlViewFactory.create(outputStream, HtmlReport.getCssUrl()); final Viewable view = factory.createSpecificationItem(this.item); assertThat(view, instanceOf(HtmlSpecificationItem.class)); } From d730ee3e21411c744f6256123a76d7d3cafff105 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sun, 22 Jul 2018 12:23:52 +0200 Subject: [PATCH 29/60] #163: Added missing license header. Task-Url: https://github.com/itsallcode/openfasttrace/issues/163 --- .../html/TestHtmlReportCssInlining.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java index 70db2767..20ad5d87 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java @@ -1,5 +1,27 @@ package org.itsallcode.openfasttrace.report.html; +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertThat; @@ -55,4 +77,4 @@ public void testInliningUnreadableCssThrowsException() throws IOException final ViewableContainer view = factory.createView("foo", "bar"); view.render(); } -} \ No newline at end of file +} From 5b06f97505c4d0bafbd050f732e5008d660ff7e5 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Wed, 25 Jul 2018 04:47:23 +0200 Subject: [PATCH 30/60] #163: Replaced system rule with ByteArrayOutputStream. Task-Url: https://github.com/itsallcode/openfasttrace/issues/163 --- .../report/html/TestHtmlReportCssInlining.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java index 20ad5d87..c841d4b0 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java @@ -25,6 +25,7 @@ import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertThat; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; @@ -35,7 +36,6 @@ import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest; import org.junit.Rule; import org.junit.Test; -import org.junit.contrib.java.lang.system.SystemOutRule; import org.junit.rules.TemporaryFolder; public class TestHtmlReportCssInlining extends AbstractFileBasedTest @@ -44,8 +44,6 @@ public class TestHtmlReportCssInlining extends AbstractFileBasedTest @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); - @Rule - public final SystemOutRule systemOutRule = new SystemOutRule().enableLog(); // [itest->dsn~reporting.html.inline_css~1] @Test @@ -53,10 +51,11 @@ public void testHtmlReportContainsInlineCSS() throws IOException { final File cssFile = this.tempFolder.newFile("test.css"); writeTextFile(cssFile, CSS); - final HtmlViewFactory factory = HtmlViewFactory.create(System.out, cssFile.toURI().toURL()); + final ByteArrayOutputStream stream = new ByteArrayOutputStream(); + final HtmlViewFactory factory = HtmlViewFactory.create(stream, cssFile.toURI().toURL()); final ViewableContainer view = factory.createView("foo", "bar"); view.render(); - assertThat(this.systemOutRule.getLog(), containsString(CSS)); + assertThat(stream.toString(), containsString(CSS)); } @Test(expected = org.itsallcode.openfasttrace.report.ReportException.class) From 62fca2f2f18bb8c42249b6d1935490430940440a Mon Sep 17 00:00:00 2001 From: redcatbear Date: Fri, 27 Jul 2018 06:56:45 +0200 Subject: [PATCH 31/60] Added attribution by name. --- doc/design.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/design.md b/doc/design.md index ff99dd9b..fa614804 100644 --- a/doc/design.md +++ b/doc/design.md @@ -1,7 +1,12 @@ # Introduction -This document is derived from the "[arc42][bib.arc42]" architectural template. + +## Acknowledgements + +This documents structure is derived from the "[arc42][bib.arc42]" architectural template by Dr. Gernot Starke, Dr. Peter Hruschka. + +If you build your own modifications based on this document, please keep the attrbiutions. ## Terminology The terminology from the [system requirement specification][bib.srs] applies. From 9c81090101ad1fa4c312cd2b4259489b818f7d13 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Thu, 2 Aug 2018 16:17:45 +0200 Subject: [PATCH 32/60] test(#143): Skip file permissions test under windows --- .../report/html/TestHtmlReportCssInlining.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java index c841d4b0..d93ea854 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReportCssInlining.java @@ -31,9 +31,11 @@ import java.net.MalformedURLException; import java.net.URL; +import org.itsallcode.openfasttrace.report.ReportException; import org.itsallcode.openfasttrace.report.view.ViewableContainer; import org.itsallcode.openfasttrace.report.view.html.HtmlViewFactory; import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest; +import org.itsallcode.openfasttrace.testutil.OsDetector; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -58,7 +60,7 @@ public void testHtmlReportContainsInlineCSS() throws IOException assertThat(stream.toString(), containsString(CSS)); } - @Test(expected = org.itsallcode.openfasttrace.report.ReportException.class) + @Test(expected = ReportException.class) public void testInliningNonExistentCssThrowsException() throws MalformedURLException { final HtmlViewFactory factory = HtmlViewFactory.create(System.out, @@ -67,9 +69,10 @@ public void testInliningNonExistentCssThrowsException() throws MalformedURLExcep view.render(); } - @Test(expected = org.itsallcode.openfasttrace.report.ReportException.class) + @Test(expected = ReportException.class) public void testInliningUnreadableCssThrowsException() throws IOException { + OsDetector.assumeRunningOnUnix(); final File cssFile = this.tempFolder.newFile("test.css"); cssFile.setReadable(false); final HtmlViewFactory factory = HtmlViewFactory.create(System.out, cssFile.toURI().toURL()); From 5d2d3db902e7f0f10b4c5f6d0dbd98b1016a2dd0 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Thu, 2 Aug 2018 16:18:28 +0200 Subject: [PATCH 33/60] feat(#143): Unify importers for long and short tags --- .../itsallcode/openfasttrace/Converter.java | 10 +- .../itsallcode/openfasttrace/Reporter.java | 10 +- .../importer/ImporterContext.java | 8 +- .../legacytag/LegacyTagImporterFactory.java | 87 ------------------ .../importer/tag/DelegatingLineConsumer.java | 42 +++++++++ .../tag/LongTagImportingLineConsumer.java | 91 +++++++++++++++++++ .../ShortTagImportingLineConsumer.java} | 34 +++---- .../importer/tag/TagImporter.java | 88 ++++++------------ .../importer/tag/TagImporterFactory.java | 58 ++++++++++-- .../config/DescribedPathMatcher.java | 2 +- .../{legacytag => tag}/config/PathConfig.java | 4 +- .../config/TagImporterConfig.java} | 12 +-- .../openfasttrace/mode/AbstractMode.java | 6 +- ...ode.openfasttrace.importer.ImporterFactory | 1 - .../TestInitializingServiceLoader.java | 4 +- .../importer/ImporterFactoryTestBase.java | 7 ++ .../importer/TestImporterContext.java | 4 +- .../importer/tag/TestTagImporter.java | 7 +- .../importer/tag/TestTagImporterFactory.java | 5 +- .../TestTagImporterFactoryWithConfig.java} | 24 ++--- .../TestTagImporterWithConfig.java} | 19 ++-- .../config/DescribedPathMatcherTest.java | 2 +- .../config/TestPathConfig.java | 3 +- 23 files changed, 297 insertions(+), 231 deletions(-) delete mode 100644 src/main/java/org/itsallcode/openfasttrace/importer/legacytag/LegacyTagImporterFactory.java create mode 100644 src/main/java/org/itsallcode/openfasttrace/importer/tag/DelegatingLineConsumer.java create mode 100644 src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java rename src/main/java/org/itsallcode/openfasttrace/importer/{legacytag/LegacyTagImporter.java => tag/ShortTagImportingLineConsumer.java} (80%) rename src/main/java/org/itsallcode/openfasttrace/importer/{legacytag => tag}/config/DescribedPathMatcher.java (97%) rename src/main/java/org/itsallcode/openfasttrace/importer/{legacytag => tag}/config/PathConfig.java (97%) rename src/main/java/org/itsallcode/openfasttrace/importer/{legacytag/config/LegacyTagImporterConfig.java => tag/config/TagImporterConfig.java} (79%) rename src/test/java/org/itsallcode/openfasttrace/importer/{legacytag/TestLegacyTagImporterFactory.java => tag/TestTagImporterFactoryWithConfig.java} (82%) rename src/test/java/org/itsallcode/openfasttrace/importer/{legacytag/TestLegacyTagImporter.java => tag/TestTagImporterWithConfig.java} (92%) rename src/test/java/org/itsallcode/openfasttrace/importer/{legacytag => tag}/config/DescribedPathMatcherTest.java (98%) rename src/test/java/org/itsallcode/openfasttrace/importer/{legacytag => tag}/config/TestPathConfig.java (96%) diff --git a/src/main/java/org/itsallcode/openfasttrace/Converter.java b/src/main/java/org/itsallcode/openfasttrace/Converter.java index cfe165ed..2a23bc29 100644 --- a/src/main/java/org/itsallcode/openfasttrace/Converter.java +++ b/src/main/java/org/itsallcode/openfasttrace/Converter.java @@ -27,9 +27,7 @@ import java.util.List; import org.itsallcode.openfasttrace.core.Newline; -import org.itsallcode.openfasttrace.FilterSettings; -import org.itsallcode.openfasttrace.importer.legacytag.LegacyTagImporterFactory; -import org.itsallcode.openfasttrace.importer.legacytag.config.LegacyTagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; /** * Convert between different requirements formats (e.g. from ReqM2 to Markdown) @@ -72,14 +70,14 @@ public interface Converter public Converter setNewline(Newline newline); /** - * Set the {@link LegacyTagImporterConfig} for the + * Set the {@link TagImporterConfig} for the * {@link LegacyTagImporterFactory}. * * @param config - * the {@link LegacyTagImporterConfig} to set. + * the {@link TagImporterConfig} to set. * @return a Converter instance for fluent programming */ - public Converter setLegacyTagImporterPathConfig(final LegacyTagImporterConfig config); + public Converter setLegacyTagImporterPathConfig(final TagImporterConfig config); /** * Convert the collected requirements into target requirement format diff --git a/src/main/java/org/itsallcode/openfasttrace/Reporter.java b/src/main/java/org/itsallcode/openfasttrace/Reporter.java index bb701b07..f70c8beb 100644 --- a/src/main/java/org/itsallcode/openfasttrace/Reporter.java +++ b/src/main/java/org/itsallcode/openfasttrace/Reporter.java @@ -28,9 +28,7 @@ import org.itsallcode.openfasttrace.core.Newline; import org.itsallcode.openfasttrace.core.Trace; -import org.itsallcode.openfasttrace.FilterSettings; -import org.itsallcode.openfasttrace.importer.legacytag.LegacyTagImporterFactory; -import org.itsallcode.openfasttrace.importer.legacytag.config.LegacyTagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; import org.itsallcode.openfasttrace.report.ReportVerbosity; /** @@ -83,14 +81,14 @@ public interface Reporter public Reporter setReportVerbosity(final ReportVerbosity verbosity); /** - * Set the {@link LegacyTagImporterConfig} for the + * Set the {@link TagImporterConfig} for the * {@link LegacyTagImporterFactory}. * * @param config - * the {@link LegacyTagImporterConfig} to set. + * the {@link TagImporterConfig} to set. * @return a Reporter instance for fluent programming */ - public Reporter setLegacyTagImporterPathConfig(final LegacyTagImporterConfig config); + public Reporter setLegacyTagImporterPathConfig(final TagImporterConfig config); /** * Run a trace on the input files diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java index 0ea02169..11535afc 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java @@ -23,7 +23,7 @@ */ import java.util.Objects; -import org.itsallcode.openfasttrace.importer.legacytag.config.LegacyTagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; /** * Common context shared by all {@link ImporterFactory}s. This allows importers @@ -31,7 +31,7 @@ */ public class ImporterContext { - private final LegacyTagImporterConfig tagImporterConfig; + private final TagImporterConfig tagImporterConfig; private ImporterService importerService; /** @@ -40,7 +40,7 @@ public class ImporterContext * @param tagImporterConfig * importer specific configuration. */ - public ImporterContext(final LegacyTagImporterConfig tagImporterConfig) + public ImporterContext(final TagImporterConfig tagImporterConfig) { this.tagImporterConfig = tagImporterConfig; } @@ -72,7 +72,7 @@ public ImporterService getImporterService() * * @return importer specific configuration. */ - public LegacyTagImporterConfig getTagImporterConfig() + public TagImporterConfig getTagImporterConfig() { return this.tagImporterConfig; } diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/LegacyTagImporterFactory.java b/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/LegacyTagImporterFactory.java deleted file mode 100644 index 172709f5..00000000 --- a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/LegacyTagImporterFactory.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.itsallcode.openfasttrace.importer.legacytag; - -/*- - * #%L - \* OpenFastTrace - * %% - * Copyright (C) 2016 - 2018 hamstercommunity - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import static java.util.stream.Collectors.toList; - -import java.util.List; -import java.util.Optional; -import java.util.logging.Logger; -import java.util.stream.Stream; - -import org.itsallcode.openfasttrace.importer.*; -import org.itsallcode.openfasttrace.importer.input.InputFile; -import org.itsallcode.openfasttrace.importer.legacytag.config.PathConfig; - -/** - * A {@link ImporterFactory} supporting the compact coverage tag format for - * source code. - */ -// [impl->dsn~import.short-coverage-tag~1] -public class LegacyTagImporterFactory extends ImporterFactory -{ - private static final Logger LOG = Logger.getLogger(LegacyTagImporterFactory.class.getName()); - - @Override - public boolean supportsFile(final InputFile path) - { - return findConfig(path).isPresent(); - } - - private Optional findConfig(final InputFile file) - { - return getPathConfigs()// - .peek(c -> LOG.finest(() -> "Checking config " + c + " with file " + file)) - .filter(config -> config.matches(file)) // - .peek(c -> LOG.finest(() -> "Config " + c + " matches file " + file)) // - .findFirst(); - } - - @Override - public Importer createImporter(final InputFile path, final ImportEventListener listener) - { - final Optional config = findConfig(path); - if (!config.isPresent()) - { - final List descriptions = this.getPathConfigs() // - .map(PathConfig::getDescription) // - .collect(toList()); - throw new ImporterException("File '" + path - + "' not supported for import, supported paths: " + descriptions); - } - return () -> runImporter(path, config.get(), listener); - } - - private Stream getPathConfigs() - { - return getContext().getTagImporterConfig().getPathConfigs().stream(); - } - - private void runImporter(final InputFile file, final PathConfig config, - final ImportEventListener listener) - { - LOG.finest(() -> "Creating importer for file " + file); - final LegacyTagImporter importer = new LegacyTagImporter(config, file, listener); - importer.runImport(); - } -} diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/DelegatingLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/DelegatingLineConsumer.java new file mode 100644 index 00000000..63acf3db --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/DelegatingLineConsumer.java @@ -0,0 +1,42 @@ +package org.itsallcode.openfasttrace.importer.tag; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +import java.util.List; + +import org.itsallcode.openfasttrace.importer.LineReader.LineConsumer; + +class DelegatingLineConsumer implements LineConsumer +{ + private final List delegates; + + DelegatingLineConsumer(final List delegates) + { + this.delegates = delegates; + } + + @Override + public void readLine(final int lineNumber, final String line) + { + this.delegates.forEach(delegate -> delegate.readLine(lineNumber, line)); + } +} diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java new file mode 100644 index 00000000..c3e343ad --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java @@ -0,0 +1,91 @@ +package org.itsallcode.openfasttrace.importer.tag; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.itsallcode.openfasttrace.core.SpecificationItemId; +import org.itsallcode.openfasttrace.importer.ChecksumCalculator; +import org.itsallcode.openfasttrace.importer.ImportEventListener; +import org.itsallcode.openfasttrace.importer.LineReader.LineConsumer; +import org.itsallcode.openfasttrace.importer.input.InputFile; + +// [impl->dsn~import.full-coverage-tag~1] +class LongTagImportingLineConsumer implements LineConsumer +{ + private static final Logger LOG = Logger + .getLogger(LongTagImportingLineConsumer.class.getName()); + + private static final Pattern COVERED_ID_PATTERN = SpecificationItemId.ID_PATTERN; + private static final String COVERING_ARTIFACT_TYPE_PATTERN = "\\p{Alpha}+"; + private static final String TAG_PREFIX_PATTERN = "\\["; + private static final String TAG_SUFFIX_PATTERN = "\\]"; + private static final String LONG_TAG_PATTERN_REGEX = TAG_PREFIX_PATTERN // + + "(" + COVERING_ARTIFACT_TYPE_PATTERN + ")" // + + "->" // + + "(" + COVERED_ID_PATTERN + ")" // + + TAG_SUFFIX_PATTERN; + + private final InputFile file; + private final ImportEventListener listener; + private final Pattern tagPattern; + + LongTagImportingLineConsumer(final InputFile file, final ImportEventListener listener) + { + this.file = file; + this.listener = listener; + this.tagPattern = Pattern.compile(LONG_TAG_PATTERN_REGEX); + } + + @Override + public void readLine(final int lineNumber, final String line) + { + final Matcher matcher = this.tagPattern.matcher(line); + int counter = 0; + while (matcher.find()) + { + this.listener.beginSpecificationItem(); + this.listener.setLocation(this.file.getPath(), lineNumber); + final SpecificationItemId coveredId = SpecificationItemId.parseId(matcher.group(2)); + final String generatedName = generateName(coveredId, lineNumber, counter); + final SpecificationItemId generatedId = SpecificationItemId.createId(matcher.group(1), + generatedName, 0); + + LOG.finest(() -> "File " + this.file + ":" + lineNumber + ": found '" + generatedId + + "' covering id '" + coveredId + "'"); + this.listener.setId(generatedId); + this.listener.addCoveredId(coveredId); + this.listener.endSpecificationItem(); + counter++; + } + } + + private String generateName(final SpecificationItemId coveredId, final int lineNumber, + final int counter) + { + final String uniqueName = this.file.getPath() + lineNumber + counter + coveredId.toString(); + final String checksum = Long.toString(ChecksumCalculator.calculateCrc32(uniqueName)); + return coveredId.getName() + "-" + checksum; + } +} diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/LegacyTagImporter.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java similarity index 80% rename from src/main/java/org/itsallcode/openfasttrace/importer/legacytag/LegacyTagImporter.java rename to src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java index 65a0a2e8..1eb987f0 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/LegacyTagImporter.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java @@ -1,4 +1,4 @@ -package org.itsallcode.openfasttrace.importer.legacytag; +package org.itsallcode.openfasttrace.importer.tag; /*- * #%L @@ -27,41 +27,43 @@ import java.util.regex.Pattern; import org.itsallcode.openfasttrace.core.SpecificationItemId; -import org.itsallcode.openfasttrace.importer.*; +import org.itsallcode.openfasttrace.importer.ChecksumCalculator; +import org.itsallcode.openfasttrace.importer.ImportEventListener; +import org.itsallcode.openfasttrace.importer.ImporterException; +import org.itsallcode.openfasttrace.importer.LineReader.LineConsumer; import org.itsallcode.openfasttrace.importer.input.InputFile; -import org.itsallcode.openfasttrace.importer.legacytag.config.PathConfig; +import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; // [impl->dsn~import.short-coverage-tag~1] -class LegacyTagImporter implements Importer +class ShortTagImportingLineConsumer implements LineConsumer { - private static final Logger LOG = Logger.getLogger(LegacyTagImporter.class.getName()); + private static final Logger LOG = Logger + .getLogger(ShortTagImportingLineConsumer.class.getName()); private static final String TAG_PREFIX = "\\[\\["; private static final String TAG_SUFFIX = "\\]\\]"; + private static final String SHORT_TAG_PATTERN_REGEX = TAG_PREFIX // + + SpecificationItemId.ITEM_NAME_PATTERN // + + ":" // + + SpecificationItemId.ITEM_REVISION_PATTERN // + + TAG_SUFFIX; + private final PathConfig pathConfig; private final ImportEventListener listener; private final InputFile file; private final Pattern tagPattern; - LegacyTagImporter(final PathConfig pathConfig, final InputFile file, + ShortTagImportingLineConsumer(final PathConfig pathConfig, final InputFile file, final ImportEventListener listener) { this.pathConfig = pathConfig; this.file = file; this.listener = listener; - this.tagPattern = Pattern.compile(TAG_PREFIX // - + SpecificationItemId.ITEM_NAME_PATTERN + ":" - + SpecificationItemId.ITEM_REVISION_PATTERN + TAG_SUFFIX); + this.tagPattern = Pattern.compile(SHORT_TAG_PATTERN_REGEX); } @Override - public void runImport() - { - final LineReader reader = LineReader.create(this.file); - reader.readLines(this::processLine); - } - - private void processLine(final int lineNumber, final String line) + public void readLine(final int lineNumber, final String line) { final Matcher matcher = this.tagPattern.matcher(line); int counter = 0; diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporter.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporter.java index e56e2d7f..72213498 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporter.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporter.java @@ -22,15 +22,16 @@ * #L% */ -import java.io.BufferedReader; -import java.io.IOException; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; -import org.itsallcode.openfasttrace.core.SpecificationItemId; -import org.itsallcode.openfasttrace.importer.*; +import org.itsallcode.openfasttrace.importer.ImportEventListener; +import org.itsallcode.openfasttrace.importer.Importer; +import org.itsallcode.openfasttrace.importer.LineReader; +import org.itsallcode.openfasttrace.importer.LineReader.LineConsumer; import org.itsallcode.openfasttrace.importer.input.InputFile; +import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; /** * {@link Importer} for tags in source code files. @@ -38,74 +39,37 @@ // [impl->dsn~import.full-coverage-tag~1] class TagImporter implements Importer { - private static final Logger LOG = Logger.getLogger(TagImporter.class.getName()); - private static final Pattern COVERED_ID_PATTERN = SpecificationItemId.ID_PATTERN; - private static final String COVERING_ARTIFACT_TYPE_PATTERN = "\\p{Alpha}+"; - private static final String TAG_PREFIX_PATTERN = "\\["; - private static final String TAG_SUFFIX_PATTERN = "\\]"; - + private final LineConsumer lineImporter; private final InputFile file; - private final ImportEventListener listener; - private final Pattern tagPattern; - public TagImporter(final InputFile file, final ImportEventListener listener) + public TagImporter(final Optional config, final InputFile file, + final ImportEventListener listener) { - this.file = file; - this.listener = listener; - this.tagPattern = Pattern.compile(TAG_PREFIX_PATTERN // - + "(" + COVERING_ARTIFACT_TYPE_PATTERN + ")" // - + "->" // - + "(" + COVERED_ID_PATTERN + ")" // - + TAG_SUFFIX_PATTERN); + this(createLineImporter(config, file, listener), file); } - @Override - public void runImport() + TagImporter(final LineConsumer lineImporter, final InputFile file) { - String line; - int lineNumber = 0; - try (BufferedReader reader = this.file.createReader()) - { - while ((line = reader.readLine()) != null) - { - ++lineNumber; - processLine(lineNumber, line); - } - } - catch (final IOException exception) - { - throw new ImporterException("Error reading \"" + this.file + "\" at " + lineNumber, - exception); - } + this.lineImporter = lineImporter; + this.file = file; } - private void processLine(final int lineNumber, final String line) + private static LineConsumer createLineImporter(final Optional config, + final InputFile file, final ImportEventListener listener) { - final Matcher matcher = this.tagPattern.matcher(line); - int counter = 0; - while (matcher.find()) + final List importers = new ArrayList<>(); + importers.add(new LongTagImportingLineConsumer(file, listener)); + if (config.isPresent()) { - this.listener.beginSpecificationItem(); - this.listener.setLocation(this.file.getPath(), lineNumber); - final SpecificationItemId coveredId = SpecificationItemId.parseId(matcher.group(2)); - final String generatedName = generateName(coveredId, lineNumber, counter); - final SpecificationItemId generatedId = SpecificationItemId.createId(matcher.group(1), - generatedName, 0); - - LOG.finest(() -> "File " + this.file + ":" + lineNumber + ": found '" + generatedId - + "' covering id '" + coveredId + "'"); - this.listener.setId(generatedId); - this.listener.addCoveredId(coveredId); - this.listener.endSpecificationItem(); - counter++; + importers.add(new ShortTagImportingLineConsumer(config.get(), file, listener)); } + return new DelegatingLineConsumer(importers); } - private String generateName(final SpecificationItemId coveredId, final int lineNumber, - final int counter) + @Override + public void runImport() { - final String uniqueName = this.file.getPath() + lineNumber + counter + coveredId.toString(); - final String checksum = Long.toString(ChecksumCalculator.calculateCrc32(uniqueName)); - return coveredId.getName() + "-" + checksum; + final LineReader reader = LineReader.create(this.file); + reader.readLines(this.lineImporter); } } diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java index 1add6b20..37a17573 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java @@ -1,5 +1,12 @@ package org.itsallcode.openfasttrace.importer.tag; +import static java.util.stream.Collectors.toList; + +import java.util.Optional; +import java.util.logging.Logger; +import java.util.regex.Pattern; +import java.util.stream.Stream; + /*- * #%L * OpenFastTrace @@ -21,24 +28,63 @@ * . * #L% */ - import org.itsallcode.openfasttrace.importer.*; import org.itsallcode.openfasttrace.importer.input.InputFile; +import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; /** * {@link ImporterFactory} for tags in source code files. */ // [impl->dsn~import.full-coverage-tag~1] -public class TagImporterFactory extends RegexMatchingImporterFactory +public class TagImporterFactory extends ImporterFactory { - public TagImporterFactory() + private static final Logger LOG = Logger.getLogger(TagImporterFactory.class.getName()); + + private static final String DEFAULT_FILE_REGEX = "(?i).*\\.java"; + private static final Pattern DEFAULT_FILE_PATTERN = Pattern.compile(DEFAULT_FILE_REGEX); + + @Override + public boolean supportsFile(final InputFile path) + { + return supportsDefaultFile(path) || supportsConfiguredFile(path); + } + + private boolean supportsConfiguredFile(final InputFile path) { - super("(?i).*\\.java"); + return findConfig(path).isPresent(); + } + + public boolean supportsDefaultFile(final InputFile file) + { + return DEFAULT_FILE_PATTERN.matcher(file.getPath()).matches(); + } + + private Optional findConfig(final InputFile file) + { + return getPathConfigs()// + .peek(c -> LOG.finest(() -> "Checking config " + c + " with file " + file)) + .filter(config -> config.matches(file)) // + .peek(c -> LOG.finest(() -> "Config " + c + " matches file " + file)) // + .findFirst(); } @Override - public Importer createImporter(final InputFile file, final ImportEventListener listener) + public Importer createImporter(final InputFile path, final ImportEventListener listener) + { + if (!supportsFile(path)) + { + throw new ImporterException( + "File '" + path + "' not supported for import. Supported file name patterns: " + + DEFAULT_FILE_REGEX + " and " + getPathConfigs().collect(toList())); + } + final Optional config = findConfig(path); + return new TagImporter(config, path, listener); + } + + private Stream getPathConfigs() { - return new TagImporter(file, listener); + final TagImporterConfig config = getContext().getTagImporterConfig(); + return config == null ? Stream.empty() : config.getPathConfigs().stream(); } } diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/DescribedPathMatcher.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/DescribedPathMatcher.java similarity index 97% rename from src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/DescribedPathMatcher.java rename to src/main/java/org/itsallcode/openfasttrace/importer/tag/config/DescribedPathMatcher.java index 49cf118e..27d1ef3b 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/DescribedPathMatcher.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/DescribedPathMatcher.java @@ -1,4 +1,4 @@ -package org.itsallcode.openfasttrace.importer.legacytag.config; +package org.itsallcode.openfasttrace.importer.tag.config; /*- * #%L diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/PathConfig.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/PathConfig.java similarity index 97% rename from src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/PathConfig.java rename to src/main/java/org/itsallcode/openfasttrace/importer/tag/config/PathConfig.java index a624bc45..abed76e4 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/PathConfig.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/PathConfig.java @@ -1,4 +1,4 @@ -package org.itsallcode.openfasttrace.importer.legacytag.config; +package org.itsallcode.openfasttrace.importer.tag.config; /*- * #%L @@ -32,7 +32,7 @@ /** * The configuration of a single path that is imported by - * {@link LegacyTagImporter}. Use {@link #builder()} to create a new instance. + * {@link ShortTagImportingLineConsumer}. Use {@link #builder()} to create a new instance. */ public class PathConfig { diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/LegacyTagImporterConfig.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java similarity index 79% rename from src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/LegacyTagImporterConfig.java rename to src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java index 14924365..7d1a4ff8 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/legacytag/config/LegacyTagImporterConfig.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java @@ -1,4 +1,4 @@ -package org.itsallcode.openfasttrace.importer.legacytag.config; +package org.itsallcode.openfasttrace.importer.tag.config; /*- * #%L @@ -27,9 +27,9 @@ import java.util.List; /** - * Configuration for the {@link LegacyTagImporter}. + * Configuration for the {@link ShortTagImportingLineConsumer}. */ -public class LegacyTagImporterConfig +public class TagImporterConfig { private final List pathConfigs; @@ -39,7 +39,7 @@ public class LegacyTagImporterConfig * @param pathConfigs * a list of {@link PathConfig} objects. */ - public LegacyTagImporterConfig(final List pathConfigs) + public TagImporterConfig(final List pathConfigs) { this.pathConfigs = pathConfigs; } @@ -47,9 +47,9 @@ public LegacyTagImporterConfig(final List pathConfigs) /** * Creates a new, empty configuration. */ - public static LegacyTagImporterConfig empty() + public static TagImporterConfig empty() { - return new LegacyTagImporterConfig(emptyList()); + return new TagImporterConfig(emptyList()); } public List getPathConfigs() diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java index 81688b25..ca73705a 100644 --- a/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java +++ b/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java @@ -33,14 +33,14 @@ import org.itsallcode.openfasttrace.core.*; import org.itsallcode.openfasttrace.core.serviceloader.InitializingServiceLoader; import org.itsallcode.openfasttrace.importer.*; -import org.itsallcode.openfasttrace.importer.legacytag.config.LegacyTagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; abstract class AbstractMode> { protected final List inputs = new ArrayList<>(); protected Newline newline = Newline.UNIX; private FilterSettings filterSettings = FilterSettings.createAllowingEverything(); - private LegacyTagImporterConfig tagImporterConfig = LegacyTagImporterConfig.empty(); + private TagImporterConfig tagImporterConfig = TagImporterConfig.empty(); protected abstract T self(); @@ -68,7 +68,7 @@ public T setFilters(final FilterSettings filterSettings) return self(); } - public T setLegacyTagImporterPathConfig(final LegacyTagImporterConfig tagImporterConfig) + public T setLegacyTagImporterPathConfig(final TagImporterConfig tagImporterConfig) { this.tagImporterConfig = tagImporterConfig; return self(); diff --git a/src/main/resources/META-INF/services/org.itsallcode.openfasttrace.importer.ImporterFactory b/src/main/resources/META-INF/services/org.itsallcode.openfasttrace.importer.ImporterFactory index e8fd2f2b..9261c57b 100644 --- a/src/main/resources/META-INF/services/org.itsallcode.openfasttrace.importer.ImporterFactory +++ b/src/main/resources/META-INF/services/org.itsallcode.openfasttrace.importer.ImporterFactory @@ -1,5 +1,4 @@ org.itsallcode.openfasttrace.importer.markdown.MarkdownImporterFactory org.itsallcode.openfasttrace.importer.specobject.SpecobjectImporterFactory org.itsallcode.openfasttrace.importer.tag.TagImporterFactory -org.itsallcode.openfasttrace.importer.legacytag.LegacyTagImporterFactory org.itsallcode.openfasttrace.importer.zip.ZipFileImporterFactory diff --git a/src/test/java/org/itsallcode/openfasttrace/core/serviceloader/TestInitializingServiceLoader.java b/src/test/java/org/itsallcode/openfasttrace/core/serviceloader/TestInitializingServiceLoader.java index 4433659f..6dc2e58f 100644 --- a/src/test/java/org/itsallcode/openfasttrace/core/serviceloader/TestInitializingServiceLoader.java +++ b/src/test/java/org/itsallcode/openfasttrace/core/serviceloader/TestInitializingServiceLoader.java @@ -34,7 +34,6 @@ import org.itsallcode.openfasttrace.exporter.specobject.SpecobjectExporterFactory; import org.itsallcode.openfasttrace.importer.ImporterContext; import org.itsallcode.openfasttrace.importer.ImporterFactory; -import org.itsallcode.openfasttrace.importer.legacytag.LegacyTagImporterFactory; import org.itsallcode.openfasttrace.importer.markdown.MarkdownImporterFactory; import org.itsallcode.openfasttrace.importer.specobject.SpecobjectImporterFactory; import org.itsallcode.openfasttrace.importer.tag.TagImporterFactory; @@ -65,11 +64,10 @@ public void testImporterFactoriesRegistered() final ImporterContext context = new ImporterContext(null); final List services = getRegisteredServices(ImporterFactory.class, context); - assertThat(services, hasSize(5)); + assertThat(services, hasSize(4)); assertThat(services, contains(instanceOf(MarkdownImporterFactory.class), // instanceOf(SpecobjectImporterFactory.class), // instanceOf(TagImporterFactory.class), // - instanceOf(LegacyTagImporterFactory.class), // instanceOf(ZipFileImporterFactory.class))); for (final ImporterFactory importerFactory : services) { diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java b/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java index 3fab6134..901a3906 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java @@ -1,5 +1,7 @@ package org.itsallcode.openfasttrace.importer; +import static java.util.Collections.emptyList; + /*- * #%L \* OpenFastTrace @@ -25,12 +27,14 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.when; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import org.itsallcode.openfasttrace.importer.input.InputFile; +import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -55,6 +59,8 @@ public abstract class ImporterFactoryTestBase public void initMocks() { MockitoAnnotations.initMocks(this); + when(this.contextMock.getTagImporterConfig()) + .thenReturn(new TagImporterConfig(emptyList())); } @Test @@ -97,6 +103,7 @@ public void testInit() public void testMissingContextThrowsException() { final T factory = createFactory(); + factory.init(null); this.thrown.expect(NullPointerException.class); this.thrown.expectMessage(equalTo("Context was not initialized")); factory.getContext(); diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java index e98d0cf2..5652513d 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java @@ -25,7 +25,7 @@ import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; -import org.itsallcode.openfasttrace.importer.legacytag.config.LegacyTagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -34,7 +34,7 @@ public class TestImporterContext { @Mock - private LegacyTagImporterConfig configMock; + private TagImporterConfig configMock; @Mock private ImporterService importerServiceMock; diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporter.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporter.java index 59b0a7dc..4b8adf31 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporter.java @@ -35,6 +35,7 @@ import org.itsallcode.openfasttrace.core.SpecificationItem; import org.itsallcode.openfasttrace.core.SpecificationItemId; +import org.itsallcode.openfasttrace.importer.ImporterContext; import org.itsallcode.openfasttrace.importer.SpecificationListBuilder; import org.itsallcode.openfasttrace.importer.input.InputFile; import org.itsallcode.openfasttrace.importer.input.StreamInput; @@ -48,7 +49,7 @@ // [utest->dsn~import.full-coverage-tag~1] public class TestTagImporter { - private static final String FILENAME = "testfilename"; + private static final String FILENAME = "testfilename.java"; private static final SpecificationItemId ID1 = id("artifactTypeA", "name1", 1); private static final SpecificationItemId ID2 = id("artifactTypeB", "name2.suffix", 2); private static final SpecificationItemId ID3 = id("artifactTypeC", "prefix.name3", 3); @@ -288,7 +289,9 @@ private List runImporter(final String content) final SpecificationListBuilder builder = SpecificationListBuilder.create(); final InputFile file = StreamInput.forReader(Paths.get(FILENAME), new BufferedReader(new StringReader(content))); - new TagImporterFactory().createImporter(file, builder).runImport(); + final TagImporterFactory factory = new TagImporterFactory(); + factory.init(new ImporterContext(null)); + factory.createImporter(file, builder).runImport(); return builder.build(); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactory.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactory.java index 1d1581c4..89bfd0af 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactory.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactory.java @@ -26,6 +26,7 @@ import java.util.List; +import org.itsallcode.openfasttrace.importer.ImporterContext; import org.itsallcode.openfasttrace.importer.ImporterFactoryTestBase; /** @@ -37,7 +38,9 @@ public class TestTagImporterFactory extends ImporterFactoryTestBasedsn~import.short-coverage-tag~1] -public class TestLegacyTagImporterFactory +public class TestTagImporterFactoryWithConfig { private static final String PATH1 = "path1"; private static final String PATH2 = "path2"; @@ -98,7 +99,8 @@ public void testFactoryDoesNotSupportsFile() @Test(expected = ImporterException.class) public void testFactoryThrowsExceptionForUnsupportedFile() { - createImporter(configure(glob(PATH1)), Paths.get(PATH2)); + final Importer importer = createImporter(configure(glob(PATH1)), Paths.get(PATH2)); + assertThat(importer, instanceOf(TagImporter.class)); } @Test @@ -117,27 +119,27 @@ public void testFactoryThrowsExceptionForMissingFile() throws IOException importer.runImport(); } - private void assertSupportsFile(final LegacyTagImporterConfig config, final String path, + private void assertSupportsFile(final TagImporterConfig config, final String path, final boolean expected) { final InputFile file = InputFile.forPath(Paths.get(path)); assertThat(create(config).supportsFile(file), equalTo(expected)); } - private Importer createImporter(final LegacyTagImporterConfig config, final Path path) + private Importer createImporter(final TagImporterConfig config, final Path path) { final InputFile file = InputFile.forPath(path, StandardCharsets.UTF_8); return create(config).createImporter(file, this.listenerMock); } - private LegacyTagImporterConfig configure(final PathConfig... pathConfigs) + private TagImporterConfig configure(final PathConfig... pathConfigs) { - return new LegacyTagImporterConfig(asList(pathConfigs)); + return new TagImporterConfig(asList(pathConfigs)); } - private LegacyTagImporterFactory create(final LegacyTagImporterConfig config) + private TagImporterFactory create(final TagImporterConfig config) { - final LegacyTagImporterFactory factory = new LegacyTagImporterFactory(); + final TagImporterFactory factory = new TagImporterFactory(); factory.init(this.contextMock); when(this.contextMock.getTagImporterConfig()).thenReturn(config); return factory; diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/legacytag/TestLegacyTagImporter.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java similarity index 92% rename from src/test/java/org/itsallcode/openfasttrace/importer/legacytag/TestLegacyTagImporter.java rename to src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java index fe99840c..87edd163 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/legacytag/TestLegacyTagImporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java @@ -1,4 +1,4 @@ -package org.itsallcode.openfasttrace.importer.legacytag; +package org.itsallcode.openfasttrace.importer.tag; /*- * #%L @@ -21,21 +21,19 @@ * . * #L% */ - -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import java.io.BufferedReader; import java.io.StringReader; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Optional; import org.itsallcode.openfasttrace.core.SpecificationItemId; import org.itsallcode.openfasttrace.importer.ImportEventListener; import org.itsallcode.openfasttrace.importer.input.InputFile; import org.itsallcode.openfasttrace.importer.input.StreamInput; -import org.itsallcode.openfasttrace.importer.legacytag.config.PathConfig; +import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; @@ -43,7 +41,7 @@ import org.mockito.MockitoAnnotations; // [utest->dsn~import.short-coverage-tag~1] -public class TestLegacyTagImporter +public class TestTagImporterWithConfig { private static final String COVERED_ITEM_NAME1 = "covered_name1"; private static final String COVERED_ITEM_NAME2 = "covered_name2"; @@ -85,13 +83,14 @@ public void testFileWithoutMatchingTag() } @Test - public void testFileWithNewTagFormat() + public void testFileWithNewTagFormatAlsoSupported() { final String itemName = "coveredtype~coveredname~1"; // do not inline to // avoid error in // self-trace runImport("[type->" + itemName + "]"); - verifyZeroInteractions(this.listenerMock); + verify(this.listenerMock) + .setId(SpecificationItemId.createId("type", "coveredname" + "-3264583751", 0)); } @Test @@ -160,6 +159,6 @@ private void runImport(final String content) final InputFile file = StreamInput.forReader(FILE, new BufferedReader(new StringReader(content))); - new LegacyTagImporter(this.configMock, file, this.listenerMock).runImport(); + new TagImporter(Optional.of(this.configMock), file, this.listenerMock).runImport(); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/legacytag/config/DescribedPathMatcherTest.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/config/DescribedPathMatcherTest.java similarity index 98% rename from src/test/java/org/itsallcode/openfasttrace/importer/legacytag/config/DescribedPathMatcherTest.java rename to src/test/java/org/itsallcode/openfasttrace/importer/tag/config/DescribedPathMatcherTest.java index 3b4a0c99..0e03a111 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/legacytag/config/DescribedPathMatcherTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/config/DescribedPathMatcherTest.java @@ -1,4 +1,4 @@ -package org.itsallcode.openfasttrace.importer.legacytag.config; +package org.itsallcode.openfasttrace.importer.tag.config; /*- * #%L diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/legacytag/config/TestPathConfig.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/config/TestPathConfig.java similarity index 96% rename from src/test/java/org/itsallcode/openfasttrace/importer/legacytag/config/TestPathConfig.java rename to src/test/java/org/itsallcode/openfasttrace/importer/tag/config/TestPathConfig.java index 63110f41..08d0ba73 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/legacytag/config/TestPathConfig.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/config/TestPathConfig.java @@ -1,4 +1,4 @@ -package org.itsallcode.openfasttrace.importer.legacytag.config; +package org.itsallcode.openfasttrace.importer.tag.config; /*- * #%L @@ -28,6 +28,7 @@ import java.nio.file.Paths; import org.itsallcode.openfasttrace.importer.input.InputFile; +import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; import org.junit.Test; public class TestPathConfig From c8f4a6169736ff48261c44cda3c389fabae5086e Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Fri, 3 Aug 2018 09:19:27 +0200 Subject: [PATCH 34/60] refactor(#143): Extract regex matching and iteration --- .../tag/LongTagImportingLineConsumer.java | 44 ++++++--------- .../importer/tag/RegexLineConsumer.java | 56 +++++++++++++++++++ .../tag/ShortTagImportingLineConsumer.java | 35 +++++------- 3 files changed, 87 insertions(+), 48 deletions(-) create mode 100644 src/main/java/org/itsallcode/openfasttrace/importer/tag/RegexLineConsumer.java diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java index c3e343ad..a386205b 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java @@ -28,57 +28,49 @@ import org.itsallcode.openfasttrace.core.SpecificationItemId; import org.itsallcode.openfasttrace.importer.ChecksumCalculator; import org.itsallcode.openfasttrace.importer.ImportEventListener; -import org.itsallcode.openfasttrace.importer.LineReader.LineConsumer; import org.itsallcode.openfasttrace.importer.input.InputFile; // [impl->dsn~import.full-coverage-tag~1] -class LongTagImportingLineConsumer implements LineConsumer +class LongTagImportingLineConsumer extends RegexLineConsumer { private static final Logger LOG = Logger .getLogger(LongTagImportingLineConsumer.class.getName()); private static final Pattern COVERED_ID_PATTERN = SpecificationItemId.ID_PATTERN; private static final String COVERING_ARTIFACT_TYPE_PATTERN = "\\p{Alpha}+"; - private static final String TAG_PREFIX_PATTERN = "\\["; - private static final String TAG_SUFFIX_PATTERN = "\\]"; - private static final String LONG_TAG_PATTERN_REGEX = TAG_PREFIX_PATTERN // + private static final String TAG_PREFIX = "\\["; + private static final String TAG_SUFFIX = "\\]"; + private static final String TAG_REGEX = TAG_PREFIX // + "(" + COVERING_ARTIFACT_TYPE_PATTERN + ")" // + "->" // + "(" + COVERED_ID_PATTERN + ")" // - + TAG_SUFFIX_PATTERN; + + TAG_SUFFIX; private final InputFile file; private final ImportEventListener listener; - private final Pattern tagPattern; LongTagImportingLineConsumer(final InputFile file, final ImportEventListener listener) { + super(TAG_REGEX); this.file = file; this.listener = listener; - this.tagPattern = Pattern.compile(LONG_TAG_PATTERN_REGEX); } @Override - public void readLine(final int lineNumber, final String line) + public void processMatch(final Matcher matcher, final int lineNumber, final int lineMatchCount) { - final Matcher matcher = this.tagPattern.matcher(line); - int counter = 0; - while (matcher.find()) - { - this.listener.beginSpecificationItem(); - this.listener.setLocation(this.file.getPath(), lineNumber); - final SpecificationItemId coveredId = SpecificationItemId.parseId(matcher.group(2)); - final String generatedName = generateName(coveredId, lineNumber, counter); - final SpecificationItemId generatedId = SpecificationItemId.createId(matcher.group(1), - generatedName, 0); + this.listener.beginSpecificationItem(); + this.listener.setLocation(this.file.getPath(), lineNumber); + final SpecificationItemId coveredId = SpecificationItemId.parseId(matcher.group(2)); + final String generatedName = generateName(coveredId, lineNumber, lineMatchCount); + final SpecificationItemId generatedId = SpecificationItemId.createId(matcher.group(1), + generatedName, 0); - LOG.finest(() -> "File " + this.file + ":" + lineNumber + ": found '" + generatedId - + "' covering id '" + coveredId + "'"); - this.listener.setId(generatedId); - this.listener.addCoveredId(coveredId); - this.listener.endSpecificationItem(); - counter++; - } + LOG.finest(() -> "File " + this.file + ":" + lineNumber + ": found '" + generatedId + + "' covering id '" + coveredId + "'"); + this.listener.setId(generatedId); + this.listener.addCoveredId(coveredId); + this.listener.endSpecificationItem(); } private String generateName(final SpecificationItemId coveredId, final int lineNumber, diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/RegexLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/RegexLineConsumer.java new file mode 100644 index 00000000..65785def --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/RegexLineConsumer.java @@ -0,0 +1,56 @@ +package org.itsallcode.openfasttrace.importer.tag; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.itsallcode.openfasttrace.importer.LineReader.LineConsumer; + +abstract class RegexLineConsumer implements LineConsumer +{ + private final Pattern pattern; + + RegexLineConsumer(final String patternRegex) + { + this(Pattern.compile(patternRegex)); + } + + private RegexLineConsumer(final Pattern pattern) + { + this.pattern = pattern; + } + + @Override + public void readLine(final int lineNumber, final String line) + { + final Matcher matcher = this.pattern.matcher(line); + int counter = 0; + while (matcher.find()) + { + this.processMatch(matcher, lineNumber, counter); + counter++; + } + } + + abstract void processMatch(Matcher matcher, int lineNumber, int lineMatchCount); +} diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java index 1eb987f0..895e73b0 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java @@ -24,18 +24,16 @@ import java.util.logging.Logger; import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.itsallcode.openfasttrace.core.SpecificationItemId; import org.itsallcode.openfasttrace.importer.ChecksumCalculator; import org.itsallcode.openfasttrace.importer.ImportEventListener; import org.itsallcode.openfasttrace.importer.ImporterException; -import org.itsallcode.openfasttrace.importer.LineReader.LineConsumer; import org.itsallcode.openfasttrace.importer.input.InputFile; import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; // [impl->dsn~import.short-coverage-tag~1] -class ShortTagImportingLineConsumer implements LineConsumer +class ShortTagImportingLineConsumer extends RegexLineConsumer { private static final Logger LOG = Logger .getLogger(ShortTagImportingLineConsumer.class.getName()); @@ -51,39 +49,32 @@ class ShortTagImportingLineConsumer implements LineConsumer private final PathConfig pathConfig; private final ImportEventListener listener; private final InputFile file; - private final Pattern tagPattern; ShortTagImportingLineConsumer(final PathConfig pathConfig, final InputFile file, final ImportEventListener listener) { + super(SHORT_TAG_PATTERN_REGEX); this.pathConfig = pathConfig; this.file = file; this.listener = listener; - this.tagPattern = Pattern.compile(SHORT_TAG_PATTERN_REGEX); } @Override - public void readLine(final int lineNumber, final String line) + void processMatch(final Matcher matcher, final int lineNumber, final int lineMatchCount) { - final Matcher matcher = this.tagPattern.matcher(line); - int counter = 0; - while (matcher.find()) - { - final String coveredItemName = matcher.group(1); - final String coveredItemRevision = matcher.group(2); - final SpecificationItemId coveredId = createCoveredItem(coveredItemName, - coveredItemRevision); + final String coveredItemName = matcher.group(1); + final String coveredItemRevision = matcher.group(2); + final SpecificationItemId coveredId = createCoveredItem(coveredItemName, + coveredItemRevision); - final String generatedName = generateName(coveredId, lineNumber, counter); - final SpecificationItemId tagItemId = SpecificationItemId - .createId(this.pathConfig.getTagArtifactType(), generatedName); + final String generatedName = generateName(coveredId, lineNumber, lineMatchCount); + final SpecificationItemId tagItemId = SpecificationItemId + .createId(this.pathConfig.getTagArtifactType(), generatedName); - LOG.finest(() -> "File " + this.file + ":" + lineNumber + ": found '" + tagItemId - + "' covering id '" + coveredId + "'"); + LOG.finest(() -> "File " + this.file + ":" + lineNumber + ": found '" + tagItemId + + "' covering id '" + coveredId + "'"); - addItem(lineNumber, coveredId, tagItemId); - counter++; - } + addItem(lineNumber, coveredId, tagItemId); } private void addItem(final int lineNumber, final SpecificationItemId coveredId, From 05365e129fef5b2fbfa20ae0c7c17194b5b7ad5e Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Fri, 3 Aug 2018 09:49:11 +0200 Subject: [PATCH 35/60] refactor(#143): Implement review findings --- .../tag/LongTagImportingLineConsumer.java | 12 ++++++++---- .../tag/ShortTagImportingLineConsumer.java | 4 ++-- .../openfasttrace/importer/tag/TagImporter.java | 15 ++++++++------- .../importer/tag/TagImporterFactory.java | 13 +++++++------ .../importer/tag/TestTagImporterWithConfig.java | 2 +- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java index a386205b..6016ebe7 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java @@ -23,7 +23,6 @@ */ import java.util.logging.Logger; import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.itsallcode.openfasttrace.core.SpecificationItemId; import org.itsallcode.openfasttrace.importer.ChecksumCalculator; @@ -36,14 +35,13 @@ class LongTagImportingLineConsumer extends RegexLineConsumer private static final Logger LOG = Logger .getLogger(LongTagImportingLineConsumer.class.getName()); - private static final Pattern COVERED_ID_PATTERN = SpecificationItemId.ID_PATTERN; private static final String COVERING_ARTIFACT_TYPE_PATTERN = "\\p{Alpha}+"; private static final String TAG_PREFIX = "\\["; private static final String TAG_SUFFIX = "\\]"; private static final String TAG_REGEX = TAG_PREFIX // + "(" + COVERING_ARTIFACT_TYPE_PATTERN + ")" // + "->" // - + "(" + COVERED_ID_PATTERN + ")" // + + "(" + SpecificationItemId.ID_PATTERN + ")" // + TAG_SUFFIX; private final InputFile file; @@ -76,7 +74,13 @@ public void processMatch(final Matcher matcher, final int lineNumber, final int private String generateName(final SpecificationItemId coveredId, final int lineNumber, final int counter) { - final String uniqueName = this.file.getPath() + lineNumber + counter + coveredId.toString(); + final String uniqueName = new StringBuilder() // + .append(this.file.getPath()) // + .append(lineNumber) // + .append(counter) // + .append(coveredId) // + .toString(); + // this.file.getPath() + lineNumber + counter + coveredId.toString(); final String checksum = Long.toString(ChecksumCalculator.calculateCrc32(uniqueName)); return coveredId.getName() + "-" + checksum; } diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java index 895e73b0..0f0b259e 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java @@ -40,7 +40,7 @@ class ShortTagImportingLineConsumer extends RegexLineConsumer private static final String TAG_PREFIX = "\\[\\["; private static final String TAG_SUFFIX = "\\]\\]"; - private static final String SHORT_TAG_PATTERN_REGEX = TAG_PREFIX // + private static final String TAG_REGEX = TAG_PREFIX // + SpecificationItemId.ITEM_NAME_PATTERN // + ":" // + SpecificationItemId.ITEM_REVISION_PATTERN // @@ -53,7 +53,7 @@ class ShortTagImportingLineConsumer extends RegexLineConsumer ShortTagImportingLineConsumer(final PathConfig pathConfig, final InputFile file, final ImportEventListener listener) { - super(SHORT_TAG_PATTERN_REGEX); + super(TAG_REGEX); this.pathConfig = pathConfig; this.file = file; this.listener = listener; diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporter.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporter.java index 72213498..0181c47e 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporter.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporter.java @@ -42,19 +42,20 @@ class TagImporter implements Importer private final LineConsumer lineImporter; private final InputFile file; - public TagImporter(final Optional config, final InputFile file, - final ImportEventListener listener) - { - this(createLineImporter(config, file, listener), file); - } - TagImporter(final LineConsumer lineImporter, final InputFile file) { this.lineImporter = lineImporter; this.file = file; } - private static LineConsumer createLineImporter(final Optional config, + public static TagImporter create(final Optional config, final InputFile file, + final ImportEventListener listener) + { + final LineConsumer lineConsumer = createLineConsumer(config, file, listener); + return new TagImporter(lineConsumer, file); + } + + private static LineConsumer createLineConsumer(final Optional config, final InputFile file, final ImportEventListener listener) { final List importers = new ArrayList<>(); diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java index 37a17573..c053aafb 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java @@ -63,9 +63,10 @@ public boolean supportsDefaultFile(final InputFile file) private Optional findConfig(final InputFile file) { return getPathConfigs()// - .peek(c -> LOG.finest(() -> "Checking config " + c + " with file " + file)) + .peek(config -> LOG + .finest(() -> "Checking config " + config + " with file " + file)) .filter(config -> config.matches(file)) // - .peek(c -> LOG.finest(() -> "Config " + c + " matches file " + file)) // + .peek(config -> LOG.finest(() -> "Config " + config + " matches file " + file)) // .findFirst(); } @@ -74,12 +75,12 @@ public Importer createImporter(final InputFile path, final ImportEventListener l { if (!supportsFile(path)) { - throw new ImporterException( - "File '" + path + "' not supported for import. Supported file name patterns: " - + DEFAULT_FILE_REGEX + " and " + getPathConfigs().collect(toList())); + throw new ImporterException("File '" + path + + "' cannot be imported because it does not match any supported file patterns: " + + DEFAULT_FILE_REGEX + " and " + getPathConfigs().collect(toList())); } final Optional config = findConfig(path); - return new TagImporter(config, path, listener); + return TagImporter.create(config, path, listener); } private Stream getPathConfigs() diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java index 87edd163..1aef4bd5 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java @@ -159,6 +159,6 @@ private void runImport(final String content) final InputFile file = StreamInput.forReader(FILE, new BufferedReader(new StringReader(content))); - new TagImporter(Optional.of(this.configMock), file, this.listenerMock).runImport(); + TagImporter.create(Optional.of(this.configMock), file, this.listenerMock).runImport(); } } From c63bc3332c2a290b09f53b74339b3ce3c10915a5 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Fri, 3 Aug 2018 10:00:34 +0200 Subject: [PATCH 36/60] refactor(#143): Improve error message for invalid revision --- .../openfasttrace/importer/LineReader.java | 16 +++++++++++++++- .../tag/ShortTagImportingLineConsumer.java | 2 +- .../importer/tag/TestTagImporterWithConfig.java | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/LineReader.java b/src/main/java/org/itsallcode/openfasttrace/importer/LineReader.java index ceec1c65..bba45786 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/LineReader.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/LineReader.java @@ -50,7 +50,7 @@ public void readLines(final LineConsumer consumer) while ((line = reader.readLine()) != null) { currentLineNumber = reader.getLineNumber(); - consumer.readLine(currentLineNumber, line); + processLine(consumer, currentLineNumber, line); } } catch (final IOException exception) @@ -60,6 +60,20 @@ public void readLines(final LineConsumer consumer) } } + private void processLine(final LineConsumer consumer, final int currentLineNumber, + final String line) + { + try + { + consumer.readLine(currentLineNumber, line); + } + catch (final Exception e) + { + throw new ImporterException("Error processing line " + this.file.getPath() + ":" + + currentLineNumber + " (" + line + "): " + e.getMessage(), e); + } + } + @FunctionalInterface public interface LineConsumer { diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java index 0f0b259e..a1069901 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/ShortTagImportingLineConsumer.java @@ -43,7 +43,7 @@ class ShortTagImportingLineConsumer extends RegexLineConsumer private static final String TAG_REGEX = TAG_PREFIX // + SpecificationItemId.ITEM_NAME_PATTERN // + ":" // - + SpecificationItemId.ITEM_REVISION_PATTERN // + + "(\\w+)" // + TAG_SUFFIX; private final PathConfig pathConfig; diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java index 1aef4bd5..4455ee41 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterWithConfig.java @@ -31,11 +31,14 @@ import org.itsallcode.openfasttrace.core.SpecificationItemId; import org.itsallcode.openfasttrace.importer.ImportEventListener; +import org.itsallcode.openfasttrace.importer.ImporterException; import org.itsallcode.openfasttrace.importer.input.InputFile; import org.itsallcode.openfasttrace.importer.input.StreamInput; import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -49,6 +52,10 @@ public class TestTagImporterWithConfig private static final String COVERED_ITEM_TYPE = "covered_type"; private static final String COVERING_ITEM_TYPE = "covering_type"; private static final String COVERED_ITEM_NAME_PREFIX = "prefix."; + private static final String INVALID_REVISION = "invalidRevision"; + + @Rule + public ExpectedException thrown = ExpectedException.none(); @Mock private PathConfig configMock; @@ -131,6 +138,16 @@ public void testFileWithLegacyTagFormatTwoTagsInSameLine() this.inOrderListener.verifyNoMoreInteractions(); } + @Test + public void testNonIntegerRevisionRejected() + { + this.thrown.expect(ImporterException.class); + this.thrown.expectMessage("Error processing line dummy:1 ([[" + COVERED_ITEM_NAME1 + ":" + + INVALID_REVISION + "]]): Error parsing revision '" + INVALID_REVISION + + "' for item '" + COVERED_ITEM_NAME1 + "'"); + runImport("[[" + COVERED_ITEM_NAME1 + ":" + INVALID_REVISION + "]]"); + } + @Test public void testFileWithLegacyTagFormatWithPrefix() { From b8fdaaaec109822dd79a30e9aeb21e861493b8ee Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Fri, 3 Aug 2018 12:11:31 +0200 Subject: [PATCH 37/60] test(#143): Add test to improve coverage --- .../importer/tag/config/TestPathConfig.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/tag/config/TestPathConfig.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/config/TestPathConfig.java index 08d0ba73..8a304983 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/tag/config/TestPathConfig.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/config/TestPathConfig.java @@ -25,10 +25,12 @@ import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; +import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; import org.itsallcode.openfasttrace.importer.input.InputFile; -import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; import org.junit.Test; public class TestPathConfig @@ -97,6 +99,24 @@ public void testGetPatternWithRegexPrefix() assertThat(create("regex:pattern").getDescription(), equalTo("regex:pattern")); } + @Test + public void testBuilder() + { + final List paths = new ArrayList<>(); + final String pattern = "pattern"; + final String coveredItemArtifactType = "coveredItemArtifactType"; + final String coveredItemNamePrefix = "coveredItemNamePrefix"; + final String tagArtifactType = "tagArtifactType"; + final PathConfig config = PathConfig.builder().pathListMatcher(paths) + .patternPathMatcher(pattern).coveredItemArtifactType(coveredItemArtifactType) + .coveredItemNamePrefix(coveredItemNamePrefix).tagArtifactType(tagArtifactType) + .build(); + assertThat(config.getCoveredItemArtifactType(), equalTo(coveredItemArtifactType)); + assertThat(config.getCoveredItemNamePrefix(), equalTo(coveredItemNamePrefix)); + assertThat(config.getDescription(), equalTo("glob:" + pattern)); + assertThat(config.getTagArtifactType(), equalTo(tagArtifactType)); + } + private void assertMatches(final String pattern, final String path, final boolean expected) { final InputFile file = InputFile.forPath(Paths.get(path)); From 59dd2a2d4ec692f534e41ae4c34e2bd5d12f2bbd Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Fri, 3 Aug 2018 21:46:09 +0200 Subject: [PATCH 38/60] refactor(#143): Fix review finding --- .../openfasttrace/importer/tag/LongTagImportingLineConsumer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java index 6016ebe7..ad20b266 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/LongTagImportingLineConsumer.java @@ -80,7 +80,6 @@ private String generateName(final SpecificationItemId coveredId, final int lineN .append(counter) // .append(coveredId) // .toString(); - // this.file.getPath() + lineNumber + counter + coveredId.toString(); final String checksum = Long.toString(ChecksumCalculator.calculateCrc32(uniqueName)); return coveredId.getName() + "-" + checksum; } From c4c8c172a4f85f1b60fb98e1c97da3dd10a99540 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Fri, 3 Aug 2018 21:50:12 +0200 Subject: [PATCH 39/60] Increment version to 1.2.0 --- README.md | 6 +++--- pom.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f9567f2f..84b32b35 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Sonarcloud status: Download the executable jar at [jcenter](https://jcenter.bintray.com/org/itsallcode/openfasttrace/): -* [openfasttrace-1.1.0.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.1.0/openfasttrace-1.1.0.jar) +* [openfasttrace-1.2.0.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.2.0/openfasttrace-1.2.0.jar) ### Maven @@ -52,7 +52,7 @@ To use OpenFastTrace as a dependency in your maven project add this to your `pom org.itsallcode openfasttrace - 1.1.0 + 1.2.0 compile @@ -67,7 +67,7 @@ repositories { jcenter() } dependencies { - compile "org.itsallcode:openfasttrace:1.1.0" + compile "org.itsallcode:openfasttrace:1.2.0" } ``` diff --git a/pom.xml b/pom.xml index fe8346c5..ac5de73d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.itsallcode openfasttrace - 1.1.0 + 1.2.0 OpenFastTrace Free requirement tracking suite https://github.com/itsallcode/openfasttrace From fbde45cbce15d046373a22a2f20700c0813d99be Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 4 Aug 2018 14:33:56 +0200 Subject: [PATCH 40/60] Set location when reading items from specobject file --- .../importer/SpecificationListBuilder.java | 2 +- .../handler/SingleSpecObjectsHandlerBuilder.java | 12 ++++++------ .../handler/SpecObjectsHandlerBuilder.java | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/SpecificationListBuilder.java b/src/main/java/org/itsallcode/openfasttrace/importer/SpecificationListBuilder.java index 05708423..71a97256 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/SpecificationListBuilder.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/SpecificationListBuilder.java @@ -168,7 +168,7 @@ public void setTitle(final String title) @Override public void setLocation(final String path, final int line) { - this.location = Location.create(path, line); + this.setLocation(Location.create(path, line)); } @Override diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SingleSpecObjectsHandlerBuilder.java b/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SingleSpecObjectsHandlerBuilder.java index d2d32da8..0fb88886 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SingleSpecObjectsHandlerBuilder.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SingleSpecObjectsHandlerBuilder.java @@ -104,6 +104,12 @@ private void rememberSourceFile(final String fileName) setContainedLocationIfComplete(); } + private void rememberSourceLine(final int line) + { + this.containedLine = line; + setContainedLocationIfComplete(); + } + private void setContainedLocationIfComplete() { if (this.containedFileName != null && this.containedLine >= 1) @@ -111,10 +117,4 @@ private void setContainedLocationIfComplete() this.locationBuilder.path(this.containedFileName).line(this.containedLine); } } - - private void rememberSourceLine(final int line) - { - this.containedLine = line; - setContainedLocationIfComplete(); - } } diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SpecObjectsHandlerBuilder.java b/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SpecObjectsHandlerBuilder.java index 568b1e78..c877b893 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SpecObjectsHandlerBuilder.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SpecObjectsHandlerBuilder.java @@ -71,6 +71,7 @@ private void handleStartElement(final TreeElement elem) private void handleEndElement() { this.listener.setId(this.idBuilder.build()); + this.listener.setLocation(this.locationBuilder.build()); this.listener.endSpecificationItem(); this.listener.setLocation(this.locationBuilder.build()); this.idBuilder = null; From 8fbb02b0ab78dff49806af16e5b55c7331199fe6 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 4 Aug 2018 14:35:25 +0200 Subject: [PATCH 41/60] Log warning when importing invalid artifact names --- .../itsallcode/openfasttrace/core/SpecificationItemId.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/itsallcode/openfasttrace/core/SpecificationItemId.java b/src/main/java/org/itsallcode/openfasttrace/core/SpecificationItemId.java index 126ad777..b0878abf 100644 --- a/src/main/java/org/itsallcode/openfasttrace/core/SpecificationItemId.java +++ b/src/main/java/org/itsallcode/openfasttrace/core/SpecificationItemId.java @@ -1,5 +1,7 @@ package org.itsallcode.openfasttrace.core; +import java.util.logging.Logger; + /*- * #%L \* OpenFastTrace @@ -35,6 +37,8 @@ // [impl->dsn~specification-item-id~1] public class SpecificationItemId implements Comparable { + private static final Logger LOG = Logger.getLogger(SpecificationItemId.class.getName()); + public static final String UNKONWN_ARTIFACT_TYPE = "unkonwn"; public static final String ITEM_REVISION_PATTERN = "(\\d+)"; public static final String ITEM_NAME_PATTERN = "(\\p{Alpha}[\\w-]*(?:\\.\\p{Alpha}[\\w-]*)*)"; @@ -350,6 +354,9 @@ private void inferArtifactType() } else { + LOG.warning(() -> "Name '" + this.name + "' does not match legacy name pattern '" + + LEGACY_NAME_PATTERN + "': using artifact type '" + UNKONWN_ARTIFACT_TYPE + + "'."); this.artifactType = UNKONWN_ARTIFACT_TYPE; } } From 560b8662acc6f244897869531b1297db56342cae Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 4 Aug 2018 14:36:38 +0200 Subject: [PATCH 42/60] Update specobject exporter to add artifact type prefix to linksto item name --- .../org/itsallcode/openfasttrace/core/SpecificationItem.java | 1 - .../openfasttrace/exporter/specobject/SpecobjectExporter.java | 2 +- .../exporter/specobject/TestSpecobjectExporter.java | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/core/SpecificationItem.java b/src/main/java/org/itsallcode/openfasttrace/core/SpecificationItem.java index 2e55bf41..42fcf0be 100644 --- a/src/main/java/org/itsallcode/openfasttrace/core/SpecificationItem.java +++ b/src/main/java/org/itsallcode/openfasttrace/core/SpecificationItem.java @@ -46,7 +46,6 @@ public class SpecificationItem private SpecificationItem(final Builder builder) { - super(); this.id = builder.id; this.title = builder.title; this.description = builder.description; diff --git a/src/main/java/org/itsallcode/openfasttrace/exporter/specobject/SpecobjectExporter.java b/src/main/java/org/itsallcode/openfasttrace/exporter/specobject/SpecobjectExporter.java index f9a48401..a2f77e3a 100644 --- a/src/main/java/org/itsallcode/openfasttrace/exporter/specobject/SpecobjectExporter.java +++ b/src/main/java/org/itsallcode/openfasttrace/exporter/specobject/SpecobjectExporter.java @@ -199,7 +199,7 @@ private void writeCoveredIds(final List coveredIds) for (final SpecificationItemId coveredId : coveredIds) { this.writer.writeStartElement("provcov"); - writeElement("linksto", coveredId.getName()); + writeElement("linksto", coveredId.getArtifactType() + ":" + coveredId.getName()); writeElement("dstversion", coveredId.getRevision()); this.writer.writeEndElement(); } diff --git a/src/test/java/org/itsallcode/openfasttrace/exporter/specobject/TestSpecobjectExporter.java b/src/test/java/org/itsallcode/openfasttrace/exporter/specobject/TestSpecobjectExporter.java index 660a2dfe..2505fb69 100644 --- a/src/test/java/org/itsallcode/openfasttrace/exporter/specobject/TestSpecobjectExporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/exporter/specobject/TestSpecobjectExporter.java @@ -100,7 +100,7 @@ public void testExportSpecObjectWithOptionalElements() throws IOException, XMLSt + " \n" // + " \n" // + " \n" // - + " covered\n" // + + " feat:covered\n" // + " 1\n" // + " \n" // + " \n" // From 556c1cdfea1ffaa3c4ab918355b9aa51c95d09d2 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 4 Aug 2018 14:39:06 +0200 Subject: [PATCH 43/60] Add integration test for tracing specobject files --- .../importer/input/StreamInput.java | 16 +++ .../TestSpecobjectImportExport.java | 103 ++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 src/test/java/org/itsallcode/openfasttrace/importer/specobject/TestSpecobjectImportExport.java diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/input/StreamInput.java b/src/test/java/org/itsallcode/openfasttrace/importer/input/StreamInput.java index f30aed76..7cbddc46 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/input/StreamInput.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/input/StreamInput.java @@ -23,6 +23,7 @@ */ import java.io.BufferedReader; +import java.io.StringReader; import java.nio.file.Path; public class StreamInput implements InputFile @@ -36,6 +37,21 @@ private StreamInput(final Path path, final BufferedReader reader) this.reader = reader; } + /** + * Create an {@link InputFile} for a given file content. This is useful for + * tests to avoid using real files. + * + * @param path + * a dummy path. + * @param content + * the file content. + * @return an {@link InputFile}. + */ + public static InputFile forContent(final Path path, final String content) + { + return forReader(path, new BufferedReader(new StringReader(content))); + } + /** * Create an {@link InputFile} for a {@link BufferedReader}. This is useful * for tests to avoid using real files. diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/specobject/TestSpecobjectImportExport.java b/src/test/java/org/itsallcode/openfasttrace/importer/specobject/TestSpecobjectImportExport.java new file mode 100644 index 00000000..305e2b61 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/importer/specobject/TestSpecobjectImportExport.java @@ -0,0 +1,103 @@ +package org.itsallcode.openfasttrace.importer.specobject; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; + +import java.nio.file.Paths; +import java.util.List; + +import org.itsallcode.openfasttrace.core.*; +import org.itsallcode.openfasttrace.importer.Importer; +import org.itsallcode.openfasttrace.importer.SpecificationListBuilder; +import org.itsallcode.openfasttrace.importer.input.InputFile; +import org.itsallcode.openfasttrace.importer.input.StreamInput; +import org.junit.Test; + +import com.github.hamstercommunity.matcher.auto.AutoMatcher; + +public class TestSpecobjectImportExport +{ + @Test + public void testTraceContent() + { + final String content = "\n" + "\n" + + " \n" + " \n" + + " exampleB-3454416016\n" + + " approved\n" + " 0\n" + + " source.java\n" + + " 1\n" + " \n" + + " \n" + + " dsn:exampleB\n" + + " 1\n" + + " \n" + " \n" + + " \n" + " \n" + "\n" + + " \n" + " \n" + + " exampleB\n" + " approved\n" + + " 1\n" + + " spec.md\n" + + " 2\n" + + " Example requirement\n" + + " \n" + " utest\n" + + " impl\n" + " \n" + + " \n" + " \n" + ""; + + final Trace trace = trace(content); + assertThat(trace.getItems(), hasSize(2)); + assertThat(trace.getDefectItems(), hasSize(2)); + + final LinkedSpecificationItem tag = trace.getItems().get(0); + final LinkedSpecificationItem req = trace.getItems().get(1); + + final SpecificationItem expectedTag = new SpecificationItem.Builder() + .id("impl", "exampleB-3454416016", 0).location("source.java", 1) + .status(ItemStatus.APPROVED).addCoveredId("dsn", "exampleB", 1).build(); + final SpecificationItem expectedReq = new SpecificationItem.Builder() + .id("dsn", "exampleB", 1).location("spec.md", 2).description("Example requirement") + .addNeedsArtifactType("utest").addNeedsArtifactType("impl").build(); + + assertThat(tag.getItem(), AutoMatcher.equalTo(expectedTag)); + assertThat(req.getItem(), AutoMatcher.equalTo(expectedReq)); + } + + private Trace trace(final String content) + { + return trace(parse(content)); + } + + private Trace trace(final List items) + { + final List linkedItems = new Linker(items).link(); + return new Tracer().trace(linkedItems); + } + + private List parse(final String content) + { + final SpecificationListBuilder listener = SpecificationListBuilder.create(); + final InputFile input = StreamInput.forContent(Paths.get("dummy.xml"), content); + final Importer importer = new SpecobjectImporterFactory().createImporter(input, listener); + importer.runImport(); + return listener.build(); + } +} From fd5c585d5da6e3b9507f5b09f7486308b72aca4b Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Sat, 4 Aug 2018 17:53:17 +0200 Subject: [PATCH 44/60] Fix failing tests --- .../handler/SpecObjectsHandlerBuilder.java | 1 - .../TestSpecobjectImportExport.java | 38 ++++++++++++------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SpecObjectsHandlerBuilder.java b/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SpecObjectsHandlerBuilder.java index c877b893..a5697725 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SpecObjectsHandlerBuilder.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/specobject/handler/SpecObjectsHandlerBuilder.java @@ -73,7 +73,6 @@ private void handleEndElement() this.listener.setId(this.idBuilder.build()); this.listener.setLocation(this.locationBuilder.build()); this.listener.endSpecificationItem(); - this.listener.setLocation(this.locationBuilder.build()); this.idBuilder = null; this.locationBuilder = null; } diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/specobject/TestSpecobjectImportExport.java b/src/test/java/org/itsallcode/openfasttrace/importer/specobject/TestSpecobjectImportExport.java index 305e2b61..62cd53c4 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/specobject/TestSpecobjectImportExport.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/specobject/TestSpecobjectImportExport.java @@ -42,26 +42,38 @@ public class TestSpecobjectImportExport @Test public void testTraceContent() { - final String content = "\n" + "\n" - + " \n" + " \n" + final String content = "\n" // + + "\n" // + + " \n" // + + " \n" // + " exampleB-3454416016\n" - + " approved\n" + " 0\n" - + " source.java\n" - + " 1\n" + " \n" - + " \n" + + " approved\n" // + + " 0\n" // + + " source.java\n" // + + " 1\n" // + + " \n" // + + " \n" // + " dsn:exampleB\n" + " 1\n" - + " \n" + " \n" - + " \n" + " \n" + "\n" - + " \n" + " \n" - + " exampleB\n" + " approved\n" + + " \n" // + + " \n" // + + " \n" // + + " \n" // + + " \n" // + + " \n" // + + " exampleB\n" // + + " approved\n" // + " 1\n" + " spec.md\n" + " 2\n" + " Example requirement\n" - + " \n" + " utest\n" - + " impl\n" + " \n" - + " \n" + " \n" + ""; + + " \n" // + + " utest\n" + + " impl\n" // + + " \n" // + + " \n" // + + " \n" // + + ""; final Trace trace = trace(content); assertThat(trace.getItems(), hasSize(2)); From 5d25e6560cfc46fd890025b9c4fbed1a12167d94 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Tue, 7 Aug 2018 17:05:06 +0200 Subject: [PATCH 45/60] Increment version to 1.2.1 --- README.md | 6 +++--- pom.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 84b32b35..55a5a915 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Sonarcloud status: Download the executable jar at [jcenter](https://jcenter.bintray.com/org/itsallcode/openfasttrace/): -* [openfasttrace-1.2.0.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.2.0/openfasttrace-1.2.0.jar) +* [openfasttrace-1.2.1.jar](https://jcenter.bintray.com/org/itsallcode/openfasttrace/1.2.1/openfasttrace-1.2.1.jar) ### Maven @@ -52,7 +52,7 @@ To use OpenFastTrace as a dependency in your maven project add this to your `pom org.itsallcode openfasttrace - 1.2.0 + 1.2.1 compile @@ -67,7 +67,7 @@ repositories { jcenter() } dependencies { - compile "org.itsallcode:openfasttrace:1.2.0" + compile "org.itsallcode:openfasttrace:1.2.1" } ``` diff --git a/pom.xml b/pom.xml index ac5de73d..51914cb4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.itsallcode openfasttrace - 1.2.0 + 1.2.1 OpenFastTrace Free requirement tracking suite https://github.com/itsallcode/openfasttrace From 2e8b92286d4d27f6cbae58efa10faefae3ee17ad Mon Sep 17 00:00:00 2001 From: redcatbear Date: Fri, 14 Sep 2018 19:52:15 +0200 Subject: [PATCH 46/60] #165: Updated requirements and design. --- doc/design.md | 54 +++++++++++++ doc/system_requirements.md | 19 +++++ doc/usage.txt | 2 + pom.xml | 2 +- .../itsallcode/openfasttrace/Reporter.java | 10 +++ .../openfasttrace/cli/CliArguments.java | 36 +++++++++ .../cli/commands/TraceCommand.java | 5 +- .../openfasttrace/mode/ReportMode.java | 16 +++- .../openfasttrace/report/ReportService.java | 13 ++-- .../openfasttrace/report/Reportable.java | 9 ++- .../openfasttrace/report/html/HtmlReport.java | 2 +- .../report/plaintext/PlainTextReport.java | 74 ++++++++++++++---- .../view/html/HtmlSpecificationItem.java | 18 +++++ .../report/view/html/OriginLinkFormatter.java | 76 +++++++++++++++++++ .../openfasttrace/cli/TestCliArguments.java | 32 ++++++++ .../report/TestReportService.java | 8 +- .../report/html/TestHtmlReport.java | 2 +- .../report/plaintext/TestPlainTextReport.java | 60 +++++++++++++-- .../view/html/TestHtmlSpecificationItem.java | 32 ++++++++ .../view/html/TestOriginLinkFormatter.java | 52 +++++++++++++ 20 files changed, 478 insertions(+), 44 deletions(-) create mode 100644 src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java create mode 100644 src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java diff --git a/doc/design.md b/doc/design.md index 340e3753..b1608f71 100644 --- a/doc/design.md +++ b/doc/design.md @@ -327,6 +327,40 @@ Covers: Needs: impl, utest +#### Plain Text Report Contains Specification Item Origin +`dsn~reporting.plain-text.specification-item-origin~1` + +If enabled, the plain text report shows the origin of a specification item + +* for files: `:` + +Rationale: + +This format is recognized by most IDEs and automatically turned into a link in the IDE's console. + +Covers: + +* `req~reporting.requirement-origin~1` + +#### Plain Text Report Link Contains Specification Item Origin +`dsn~reporting.plain-text.linked-specification-item-origin~1` + +If enabled, the links in the plain text report show the origin of a specification item + +* for files: `:` + +Rationale: + +This format is recognized by most IDEs and automatically turned into a link in the IDE's console. + +Covers: + +* `req~reporting.requirement-origin~1` + +Needs: impl, utest, itest + +### HTML Report + #### HTML Report Inlines CSS `dsn~reporting.html.inline_css~1` @@ -354,6 +388,26 @@ Covers: Needs: impl, itest +#### HTML Report Contains Specification Item Origin +`dsn~reporting.html.specification-item-origin~1` + +If enabled, the HTML report shows the origin of a specification item as an HTML link pointing to the source. + +Covers: + +* `req~reporting.requirement-origin~1` + +#### HTML Report Link Contains Specification Item Origin +`dsn~reporting.html.linked-specification-item-origin~1` + +If enabled, the links in the plain text report show the origin of a specification item as an HTML link pointing to the source. + +Covers: + +* `req~reporting.requirement-origin~1` + +Needs: impl, utest, itest + # Deployment View # Concepts diff --git a/doc/system_requirements.md b/doc/system_requirements.md index 8dcb0c12..93626ead 100644 --- a/doc/system_requirements.md +++ b/doc/system_requirements.md @@ -452,6 +452,25 @@ Reports are the main way to find out if a projects requirements are covered prop #### Common Report Functions +##### Requirement Origin in Report +`req~reporting.requirement-origin~1` + +Users can choose to display the requirement origin (e.g. file and line number) in reports: + +* In the body of a specification item +* For each link to a specification item + +Rationale: + +This is especially useful for debugging since it makes finding broken sources faster. + +Covers: + +* [feat~plain-text-report~1](#plain-text-report) +* [feat~html-report~1](#html-report) + +Needs: dsn + #### Plain Text Report The plain text report is the most basic report variant. It serves two main purposes: diff --git a/doc/usage.txt b/doc/usage.txt index 9420757b..90b649a3 100644 --- a/doc/usage.txt +++ b/doc/usage.txt @@ -16,6 +16,8 @@ Tracing options: Converting options: -o, --output-format format Requirements format, one of "specobject" Defaults to "specobject" + -s, --show-origin Show the origin of specification items + (e.g. file and line number) Common options: -f, --file path The output file. Defaults to STDOUT. diff --git a/pom.xml b/pom.xml index 51914cb4..0fdc3f08 100644 --- a/pom.xml +++ b/pom.xml @@ -240,7 +240,7 @@ org.itsallcode.openfasttrace.cli.CliStarter - trace doc src/main/java src/test/java + trace -s doc src/main/java src/test/java diff --git a/src/main/java/org/itsallcode/openfasttrace/Reporter.java b/src/main/java/org/itsallcode/openfasttrace/Reporter.java index f70c8beb..f811acb7 100644 --- a/src/main/java/org/itsallcode/openfasttrace/Reporter.java +++ b/src/main/java/org/itsallcode/openfasttrace/Reporter.java @@ -90,6 +90,16 @@ public interface Reporter */ public Reporter setLegacyTagImporterPathConfig(final TagImporterConfig config); + /** + * Set whether the report should show origin information (e.g. file and line + * number) for specification items + * + * @param showOrigin + * true if origin information should be shown + * @return a Reporter instance for fluent programming + */ + public Reporter setShowOrigin(final boolean showOrigin); + /** * Run a trace on the input files */ diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java b/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java index 83295080..9715123a 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java @@ -51,6 +51,7 @@ public class CliArguments private ReportVerbosity reportVerbosity; private Set wantedArtifactTypes = Collections.emptySet(); private Set wantedTags = Collections.emptySet(); + private boolean showOrigin; /** * Get the output file path @@ -316,4 +317,39 @@ public void setT(final String tags) { setWantedTags(tags); } + + /** + * Check if origin information should be shown in reports. + * + * @return true if origin information should be shown in + * reports. + */ + public boolean getShowOrigin() + { + return this.showOrigin; + } + + /** + * Choose whether to show origin information in reports. + * + * @param showOrigin + * true if origin information should be shown in + * reports + */ + public void setShowOrigin(final boolean showOrigin) + { + this.showOrigin = showOrigin; + } + + /** + * Choose whether to show origin information in reports. + * + * @param showOrigin + * true if origin information should be shown in + * reports + */ + public void setS(final boolean showOrigin) + { + setShowOrigin(showOrigin); + } } diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java index dc94c429..3c565789 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java @@ -61,8 +61,9 @@ private Reporter createReporter() final Reporter reporter = new ReportMode(); reporter.addInputs(toPaths(this.arguments.getInputs())) // .setFilters(createFilterSettingsFromArguments()) // - .setNewline(this.arguments.getNewline()) - .setReportVerbosity(this.arguments.getReportVerbosity()); + .setNewline(this.arguments.getNewline()) // + .setReportVerbosity(this.arguments.getReportVerbosity()) // + .setShowOrigin(this.arguments.getShowOrigin()); return reporter; } diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java index 6f159bd7..c92f0101 100644 --- a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java +++ b/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java @@ -37,6 +37,7 @@ public class ReportMode extends AbstractMode implements Reporter private final Tracer tracer = new Tracer(); private final ReportService reportService = new ReportService(); private ReportVerbosity verbosity = ReportVerbosity.FAILURE_DETAILS; + private boolean showOrigin; @Override public Trace trace() @@ -48,7 +49,8 @@ public Trace trace() @Override public void reportToFileInFormat(final Trace trace, final Path output, final String format) { - this.reportService.reportTraceToPath(trace, output, format, this.verbosity, this.newline); + this.reportService.reportTraceToPath(trace, output, format, this.verbosity, this.newline, + this.showOrigin); } @Override @@ -61,7 +63,15 @@ public Reporter setReportVerbosity(final ReportVerbosity verbosity) @Override public void reportToStdOutInFormat(final Trace trace, final String format) { - this.reportService.reportTraceToStdOut(trace, format, this.verbosity, this.newline); + this.reportService.reportTraceToStdOut(trace, format, this.verbosity, this.newline, + this.showOrigin); + } + + @Override + public Reporter setShowOrigin(final boolean showOrigin) + { + this.showOrigin = showOrigin; + return this; } @Override @@ -69,4 +79,4 @@ protected ReportMode self() { return this; } -} +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java b/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java index 7ace1413..860e21f1 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java @@ -33,11 +33,11 @@ public class ReportService { public void reportTraceToPath(final Trace trace, final Path outputPath, final String format, - final ReportVerbosity verbosity, final Newline newline) + final ReportVerbosity verbosity, final Newline newline, final boolean showOrigin) { try (OutputStream outputStream = Files.newOutputStream(outputPath)) { - reportTraceToStream(trace, format, verbosity, newline, outputStream); + reportTraceToStream(trace, format, verbosity, newline, outputStream, showOrigin); } catch (final IOException e) { @@ -46,9 +46,9 @@ public void reportTraceToPath(final Trace trace, final Path outputPath, final St } public void reportTraceToStdOut(final Trace trace, final String format, - final ReportVerbosity verbosity, final Newline newline) + final ReportVerbosity verbosity, final Newline newline, final boolean showOrigin) { - reportTraceToStream(trace, format, verbosity, newline, getStdOutStream()); + reportTraceToStream(trace, format, verbosity, newline, getStdOutStream(), showOrigin); } // Using System.out by intention @@ -59,11 +59,12 @@ private PrintStream getStdOutStream() } private void reportTraceToStream(final Trace trace, final String format, - final ReportVerbosity verbosity, final Newline newline, final OutputStream outputStream) + final ReportVerbosity verbosity, final Newline newline, final OutputStream outputStream, + final boolean showOrigin) { final OutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); final Reportable report = createReport(trace, format, newline); - report.renderToStreamWithVerbosityLevel(bufferedOutputStream, verbosity); + report.renderToStreamWithVerbosityLevel(bufferedOutputStream, verbosity, showOrigin); try { bufferedOutputStream.flush(); diff --git a/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java b/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java index 2dc8833d..265c9c71 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java @@ -34,10 +34,13 @@ public interface Reportable * Render the plain text coverage stream. * * @param outputStream - * the output stream to which the stream is rendered. + * the output stream to which the stream is rendered * @param verbosity - * the level of detail that is reported. + * the level of detail that is reported + * @param showOrigin + * true if the report should contain origin + * information (e.g file and line number) */ public void renderToStreamWithVerbosityLevel(OutputStream outputStream, - ReportVerbosity verbosity); + ReportVerbosity verbosity, boolean showOrigin); } diff --git a/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java b/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java index ed3aedba..f3125a5c 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java @@ -58,7 +58,7 @@ public static URL getCssUrl() @Override public void renderToStreamWithVerbosityLevel(final OutputStream outputStream, - final ReportVerbosity verbosity) + final ReportVerbosity verbosity, final boolean showOrigin) { final ViewFactory factory = HtmlViewFactory.create(outputStream, getCssUrl()); final ViewableContainer view = factory.createView("", "Specification items by title"); diff --git a/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java b/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java index 76a61c9e..40a03b92 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java @@ -67,12 +67,12 @@ public PlainTextReport(final Trace trace, final Newline newline) @Override public void renderToStreamWithVerbosityLevel(final OutputStream outputStream, - final ReportVerbosity verbosity) + final ReportVerbosity verbosity, final boolean showOrigin) { final Charset charset = StandardCharsets.UTF_8; try (final PrintStream report = new PrintStream(outputStream, false, charset.displayName())) { - renderToPrintStreamWithVerbosityLevel(report, verbosity); + renderToPrintStreamWithVerbosityLevel(report, verbosity, showOrigin); } catch (final UnsupportedEncodingException e) { @@ -81,7 +81,7 @@ public void renderToStreamWithVerbosityLevel(final OutputStream outputStream, } private void renderToPrintStreamWithVerbosityLevel(final PrintStream report, - final ReportVerbosity verbosity) + final ReportVerbosity verbosity, final boolean showOrigin) { switch (verbosity) { @@ -102,12 +102,12 @@ private void renderToPrintStreamWithVerbosityLevel(final PrintStream report, renderSummary(report); break; case FAILURE_DETAILS: - renderFailureDetails(report); + renderFailureDetails(report, showOrigin); separateItemsFromSummary(report); renderSummary(report); break; case ALL: - renderAll(report); + renderAll(report, showOrigin); report.print(this.newline); renderSummary(report); break; @@ -225,29 +225,43 @@ private void renderMaturity(final PrintStream report, final LinkedSpecificationI } } - private void renderFailureDetails(final PrintStream report) + private void renderFailureDetails(final PrintStream report, final boolean showOrigin) { this.trace.getDefectItems().stream() // .sorted(LINKED_ITEM_BY_ID) // - .forEachOrdered(item -> renderItemDetails(report, item)); + .forEachOrdered(item -> renderItemDetails(report, item, showOrigin)); } - private void renderAll(final PrintStream report) + private void renderAll(final PrintStream report, final boolean showOrigin) { this.trace.getItems().stream() // .sorted(LINKED_ITEM_BY_ID) // - .forEachOrdered(item -> renderItemDetails(report, item)); + .forEachOrdered(item -> renderItemDetails(report, item, showOrigin)); } - private void renderItemDetails(final PrintStream report, final LinkedSpecificationItem item) + private void renderItemDetails(final PrintStream report, final LinkedSpecificationItem item, + final boolean showOrigin) { renderItemSummary(report, item); renderDescription(report, item); - renderLinks(report, item); + if (showOrigin) + { + renderOrigin(report, item); + } + renderLinks(report, item, showOrigin); renderTags(report, item); renderItemDetailsEnd(report); } + private void renderOrigin(final PrintStream report, final Location location) + { + report.print("("); + report.print(location.getPath()); + report.print(":"); + report.print(location.getLine()); + report.print(")"); + } + private void renderEmptyItemDetailsLine(final PrintStream report) { report.print("|"); @@ -271,26 +285,29 @@ private void renderDescription(final PrintStream report, final LinkedSpecificati } // [impl->dsn~reporting.plain-text.link-details~1] - private void renderLinks(final PrintStream report, final LinkedSpecificationItem item) + private void renderLinks(final PrintStream report, final LinkedSpecificationItem item, + final boolean showOrigin) { if (item.hasLinks()) { renderEmptyItemDetailsLine(report); - renderOrderedLinks(report, item); + renderOrderedLinks(report, item, showOrigin); ++this.nonEmptySections; } } - private void renderOrderedLinks(final PrintStream report, final LinkedSpecificationItem item) + private void renderOrderedLinks(final PrintStream report, final LinkedSpecificationItem item, + final boolean showOrigin) { item.getTracedLinks() // .stream() // .sorted((a, b) -> a.getOtherLinkEnd().getId() .compareTo(b.getOtherLinkEnd().getId())) // - .forEachOrdered(link -> renderLink(report, link)); + .forEachOrdered(link -> renderLink(report, link, showOrigin)); } - private void renderLink(final PrintStream report, final TracedLink link) + private void renderLink(final PrintStream report, final TracedLink link, + final boolean showOrigin) { final LinkStatus status = link.getStatus(); report.print(status.isIncoming() ? "|<-- (" : "|--> ("); @@ -298,6 +315,16 @@ private void renderLink(final PrintStream report, final TracedLink link) report.print(") "); report.print(link.getOtherLinkEnd().getId()); report.print(this.newline); + if (showOrigin) + { + final Location location = link.getOtherLinkEnd().getLocation(); + if (location != null) + { + report.print("| "); + renderOrigin(report, location); + report.print(this.newline); + } + } } private void renderTags(final PrintStream report, final LinkedSpecificationItem item) @@ -313,6 +340,21 @@ private void renderTags(final PrintStream report, final LinkedSpecificationItem } } + private void renderOrigin(final PrintStream report, final LinkedSpecificationItem item) + { + final Location location = item.getLocation(); + if (location != null) + { + renderEmptyItemDetailsLine(report); + report.print("| ("); + report.print(location.getPath()); + report.print(":"); + report.print(location.getLine()); + report.print(")"); + report.print(this.newline); + } + } + private void renderItemDetailsEnd(final PrintStream report) { if (this.nonEmptySections > 0) diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java index d6041d98..f511b188 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java @@ -35,6 +35,7 @@ public class HtmlSpecificationItem implements Viewable { + private final LinkedSpecificationItem item; private final PrintStream stream; private final MarkdownConverter converter = new MarkdownConverter(); @@ -57,6 +58,7 @@ public void render(final int level) renderRationale(indentation); renderComment(indentation); renderNeeds(indentation); + renderOrigin(indentation); renderLinks(indentation); renderEnd(indentation); } @@ -167,6 +169,14 @@ private String translateArtifactTypeCoverage(final LinkedSpecificationItem item) .collect(Collectors.joining(", ")); } + private void renderOrigin(final String indentation) + { + this.stream.print(indentation); + this.stream.print("

"); + this.stream.print(OriginLinkFormatter.format(this.item.getLocation())); + this.stream.println("

"); + } + private void renderLinks(final String indentation) { renderLinkForDirection(indentation, true); @@ -225,10 +235,18 @@ protected void renderLinkEntry(final List outLinks, final String ind { this.stream.print(" (" + link.getStatus() + ")"); } + renderLinkOrigin(link); this.stream.println(""); } } + private void renderLinkOrigin(final TracedLink link) + { + this.stream.print(" "); + this.stream.print(OriginLinkFormatter.format(link.getOtherLinkEnd().getLocation())); + this.stream.print(""); + } + protected void renderEnd(final String indentation) { this.stream.print(indentation); diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java new file mode 100644 index 00000000..ba232506 --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java @@ -0,0 +1,76 @@ +package org.itsallcode.openfasttrace.report.view.html; + +import java.net.URI; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Pattern; + +import org.itsallcode.openfasttrace.core.Location; + +public final class OriginLinkFormatter +{ + private static final Pattern PROTOCOL_PREFIX_PATTERN = Pattern + .compile("^file://|ftp://|mailto:|https?://.*"); + + private OriginLinkFormatter() + { + // prevent instantiation. + } + + public static String format(final Location location) + { + if (location == null) + { + return ""; + } + final String path = location.getPath(); + final StringBuilder builder = new StringBuilder(); + URI uri = null; + boolean validUri = false; + if (PROTOCOL_PREFIX_PATTERN.matcher(path).matches()) + { + try + { + uri = URI.create(path); + validUri = true; + } + catch (final IllegalArgumentException e) + { + validUri = false; + } + } + else + { + final Path realPath = Paths.get(unWindowsify(path)); + if (realPath.isAbsolute()) + { + uri = realPath.toUri(); + validUri = true; + } + else + { + validUri = false; + } + } + if (validUri) + { + builder.append(""); + builder.append(path); + builder.append(""); + } + else + { + builder.append(path); + } + builder.append(":"); + builder.append(location.getLine()); + return builder.toString(); + } + + private static String unWindowsify(final String path) + { + return path.replaceAll("([A-Z]:)", "/$1").replaceAll("\\\\", "/"); + } +} diff --git a/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java b/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java index 46c9661d..17d0f25f 100644 --- a/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java +++ b/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java @@ -222,4 +222,36 @@ public void testSetWantedTagsIncludingNone() assertThat(AFTER_SETTER, this.arguments.getWantedTags(), containsInAnyOrder("_", "client", "server")); } + + // [utest->dsn~reporting.plain-text.specification-item-origin~1]] + // [utest->dsn~reporting.plain-text.linked-specification-item-origin~1] + // [utest->dsn~reporting.html.specification-item-origin~1] + // [utest->dsn~reporting.html.linked-specification-item-origin~1] + @Test + public void testShowOriginDisabledByDefault() + { + assertThat(this.arguments.getShowOrigin(), is(false)); + } + + // [utest->dsn~reporting.plain-text.specification-item-origin~1]] + // [utest->dsn~reporting.plain-text.linked-specification-item-origin~1] + // [utest->dsn~reporting.html.specification-item-origin~1] + // [utest->dsn~reporting.html.linked-specification-item-origin~1] + @Test + public void testSetShowOrigin() + { + this.arguments.setShowOrigin(true); + assertThat(this.arguments.getShowOrigin(), is(true)); + } + + // [utest->dsn~reporting.plain-text.specification-item-origin~1]] + // [utest->dsn~reporting.plain-text.linked-specification-item-origin~1] + // [utest->dsn~reporting.html.specification-item-origin~1] + // [utest->dsn~reporting.html.linked-specification-item-origin~1] + @Test + public void testSetS() + { + this.arguments.setS(true); + assertThat(this.arguments.getShowOrigin(), is(true)); + } } \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java b/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java index 21839aeb..1592b3a1 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java @@ -62,7 +62,7 @@ public void prepareTest() public void testReportPlainText() { this.service.reportTraceToStdOut(this.traceMock, "plain", ReportVerbosity.MINIMAL, - Newline.UNIX); + Newline.UNIX, false); assertThat(this.systemOutRule.getLog(), equalTo("not ok\n")); } @@ -70,7 +70,7 @@ public void testReportPlainText() public void testReportHtml() { this.service.reportTraceToStdOut(this.traceMock, "html", ReportVerbosity.MINIMAL, - Newline.UNIX); + Newline.UNIX, false); assertThat(this.systemOutRule.getLog(), startsWith("")); } @@ -78,7 +78,7 @@ public void testReportHtml() public void testInvalidReportFormatThrowsIllegalArgumentException() { this.service.reportTraceToStdOut(this.traceMock, "invalid", ReportVerbosity.QUIET, - Newline.UNIX); + Newline.UNIX, false); } @Test(expected = ReportException.class) @@ -87,6 +87,6 @@ public void testReportToIllegalPathThrowsReportExpection() throws IOException final File readOnlyFile = this.temporaryFolder.newFile(); readOnlyFile.setReadOnly(); this.service.reportTraceToPath(this.traceMock, readOnlyFile.toPath(), "plain", - ReportVerbosity.QUIET, Newline.UNIX); + ReportVerbosity.QUIET, Newline.UNIX, false); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java index 6829edd5..07721e2b 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java @@ -62,7 +62,7 @@ protected String renderToString() { final OutputStream outputStream = new ByteArrayOutputStream(); final Reportable report = new HtmlReport(this.traceMock); - report.renderToStreamWithVerbosityLevel(outputStream, ReportVerbosity.ALL); + report.renderToStreamWithVerbosityLevel(outputStream, ReportVerbosity.ALL, false); final String outputAsString = outputStream.toString(); return outputAsString; } diff --git a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java index b382e6af..d3d2ceab 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java @@ -63,7 +63,7 @@ public void testOutputStreamClosed() throws IOException { final OutputStream outputStreamMock = mock(OutputStream.class); new PlainTextReport(this.traceMock, NEWLINE_SEPARATOR) - .renderToStreamWithVerbosityLevel(outputStreamMock, ReportVerbosity.SUMMARY); + .renderToStreamWithVerbosityLevel(outputStreamMock, ReportVerbosity.SUMMARY, false); verify(outputStreamMock).close(); } @@ -83,9 +83,15 @@ public void testReportLevel_Minimal_OK() private void assertReportOutput(final ReportVerbosity verbosity, final String... expectedReportLines) + { + assertReportOutput(verbosity, false, expectedReportLines); + } + + private void assertReportOutput(final ReportVerbosity verbosity, final boolean showOrigin, + final String... expectedReportLines) { final String expectedReportText = getExpectedReportText(expectedReportLines); - assertThat(getReportOutput(verbosity), matchesAllLines(expectedReportText)); + assertThat(getReportOutput(verbosity, showOrigin), matchesAllLines(expectedReportText)); } private String getExpectedReportText(final String... expectedReportLines) @@ -99,18 +105,18 @@ private String getExpectedReportText(final String... expectedReportLines) + NEWLINE_SEPARATOR; } - private String getReportOutput(final ReportVerbosity verbosity) + private String getReportOutput(final ReportVerbosity verbosity, final boolean showOrigin) { final Newline newline = NEWLINE_SEPARATOR; - return getReportOutputWithNewline(verbosity, newline); + return getReportOutputWithNewline(verbosity, newline, showOrigin); } private String getReportOutputWithNewline(final ReportVerbosity verbosity, - final Newline newline) + final Newline newline, final boolean showOrigin) { final OutputStream outputStream = new ByteArrayOutputStream(); final Reportable report = new PlainTextReport(this.traceMock, newline); - report.renderToStreamWithVerbosityLevel(outputStream, verbosity); + report.renderToStreamWithVerbosityLevel(outputStream, verbosity, showOrigin); return outputStream.toString(); } @@ -353,7 +359,7 @@ public void testReportWithDifferentLineSeparator() when(this.traceMock.hasNoDefects()).thenReturn(true); when(this.traceMock.getItems()).thenReturn(asList(itemAMock, itemBMock)); - assertThat(getReportOutputWithNewline(ReportVerbosity.ALL, separator), // + assertThat(getReportOutputWithNewline(ReportVerbosity.ALL, separator, false), // equalTo("ok - 0/0>0>0/0 - a~a~1 (dsn)" + separator// + "|" + separator // + "| This is" + separator // @@ -368,4 +374,44 @@ public void testReportWithDifferentLineSeparator() + "ok - 2 total" + separator)); } + + // [utest->dsn~reporting.plain-text.specification-item-origin~1] + // [utest->dsn~reporting.plain-text.linked-specification-item-origin~1] + @Test + public void testReportWithOriginDisplayEnabled() + { + final LinkedSpecificationItem itemMock = createLinkedItemMock("req~item.with-source~77", + "Description", 0, 1, 0, 0, 0); + when(itemMock.getNeedsArtifactTypes()).thenReturn(asList(DSN)); + when(itemMock.getCoveredArtifactTypes()).thenReturn(new HashSet<>(asList(DSN))); + final LinkedSpecificationItem other = createOtherItemMock("dsn~the-other~1"); + when(other.getLocation()).thenReturn(Location.create("baz/zoo", 10)); + final List links = new ArrayList<>(); + links.add(new TracedLink(other, LinkStatus.COVERED_SHALLOW)); + when(itemMock.getTracedLinks()).thenReturn(links); + when(itemMock.hasLinks()).thenReturn(true); + when(itemMock.getLocation()).thenReturn(Location.create("/foo/bar", 42)); + when(this.traceMock.count()).thenReturn(1); + when(this.traceMock.countDefects()).thenReturn(0); + when(this.traceMock.hasNoDefects()).thenReturn(true); + when(this.traceMock.getItems()).thenReturn(asList(itemMock)); + assertReportOutputWithOrigin(ReportVerbosity.ALL, // + "ok - 0/1>0>0/0 - req~item.with-source~77 (dsn)", // + "|", // + "| Description", // + "|", // + "| (/foo/bar:42)", // + "|", // + "|<-- ( ) dsn~the-other~1", // + "| (baz/zoo:10)", // + "|", // + "", // + "ok - 1 total"); + } + + private void assertReportOutputWithOrigin(final ReportVerbosity verbosity, + final String... expectedReportLines) + { + assertReportOutput(verbosity, true, expectedReportLines); + } } diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java index f53026e1..a2317df9 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java @@ -169,4 +169,36 @@ public void testRenderIncomingLinks() "", // ""); } + + @Test + public void testRenderOrigin() + { + final Location location = Location.create("foo/bar", 13); + final SpecificationItem item = new SpecificationItem.Builder() // + .id(ITEM_A_ID) // + .location(location) // + .build(); + final LinkedSpecificationItem linkedItem = new LinkedSpecificationItem(item); + linkedItem.addLinkToItemWithStatus(this.itemMockB, LinkStatus.COVERED_SHALLOW); + when(this.itemMockB.getLocation()) + .thenReturn(Location.create("http://example.org/foo.txt", 3)); + final Viewable view = this.factory.createSpecificationItem(linkedItem); + view.render(0); + assertOutputLines("
", // + "
", // + " " + CHECKMARK + + " name-a, rev. 1, dsn", // + "

" + ITEM_A_ID + "

", // + "

foo/bar:13

", // + "
", // + "
In: 1
", // + " ", // + "
", // + "
", // + "
", // + ""); + } } \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java new file mode 100644 index 00000000..a36bc4d8 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java @@ -0,0 +1,52 @@ +package org.itsallcode.openfasttrace.report.view.html; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.itsallcode.openfasttrace.report.view.html.OriginLinkFormatter.format; +import static org.junit.Assert.assertThat; + +import org.itsallcode.openfasttrace.core.Location; +import org.junit.Test; + +public class TestOriginLinkFormatter +{ + @Test + public void testFormatMinimalHttpLink() + { + assertThat(format(Location.create("http://example.org", 1)), + equalTo("http://example.org:1")); + } + + @Test + public void testLongerHttpLink() + { + assertThat(format(Location.create("http://example.org/foo/bar%20baz?zoo", 1)), equalTo( + "http://example.org/foo/bar%20baz?zoo:1")); + } + + @Test + public void testFormatRegularAbsoluteUnixPath() + { + assertThat(format(Location.create("/foo/bar/baz", 1111)), + equalTo("/foo/bar/baz:1111")); + } + + @Test + public void testFormatAbsoluteUnixPathWithSpecialCharacters() + { + assertThat(format(Location.create("/fo o/bär/baz", 12345678)), + equalTo("/fo o/bär/baz:12345678")); + } + + @Test + public void testFormatRelativeUnixPath() + { + assertThat(format(Location.create("foo/bar/baz", 2)), equalTo("foo/bar/baz:2")); + } + + @Test + public void testIllegalUri() + { + assertThat(format(Location.create("http://example.org/a b", 5)), + equalTo("http://example.org/a b:5")); + } +} \ No newline at end of file From 018b9cf10b45dd826ec1fad53b12883740c4a863 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Fri, 14 Sep 2018 21:10:16 +0200 Subject: [PATCH 47/60] #170: Experiment with reading version for .travis.yml from pom.xml --- .travis.yml | 5 +++-- pom.xml | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b433c501..0500db02 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,12 +16,13 @@ cache: before_script: - pip install --user codecov + - version=$(grep -oP '(?<=project\.version>)[^<]*' pom.xml) before_install: - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- script: - - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install + - mvn -Dproject.version=$version clean org.jacoco:jacoco-maven-plugin:prepare-agent install after_success: - codecov @@ -30,7 +31,7 @@ addons: coverity_scan: project: name: itsallcode/openfasttrace - version: 0.5.4 + version: $version: description: OpenFastTrace requirement tracing notification_email: christoph@users.sourceforge.net build_command_prepend: mvn clean diff --git a/pom.xml b/pom.xml index 51914cb4..dc8f4367 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.itsallcode openfasttrace - 1.2.1 + ${project.version} OpenFastTrace Free requirement tracking suite https://github.com/itsallcode/openfasttrace @@ -96,6 +96,7 @@ + 1.2.2 UTF-8 From e6ad0af2e717546fb8769d42b005ba3932bff0e3 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Fri, 14 Sep 2018 21:18:00 +0200 Subject: [PATCH 48/60] #170: remove unused colon --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0500db02..e6f59504 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ addons: coverity_scan: project: name: itsallcode/openfasttrace - version: $version: + version: $version description: OpenFastTrace requirement tracing notification_email: christoph@users.sourceforge.net build_command_prepend: mvn clean From 5aca6bdafe3a58d3707a2c5e6e955e990a5a6559 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Fri, 14 Sep 2018 21:27:14 +0200 Subject: [PATCH 49/60] #170: Turned version number back to constant in pom.xml and adapted grep in .travis.yml --- .travis.yml | 4 +++- pom.xml | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e6f59504..b3bfe1cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,12 +16,14 @@ cache: before_script: - pip install --user codecov - - version=$(grep -oP '(?<=project\.version>)[^<]*' pom.xml) + - version=$(grep -oP '(?<=^ )[^<]*' pom.xml) before_install: - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- script: + - env + - echo $version - mvn -Dproject.version=$version clean org.jacoco:jacoco-maven-plugin:prepare-agent install after_success: diff --git a/pom.xml b/pom.xml index dc8f4367..0e177e50 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.itsallcode openfasttrace - ${project.version} + 1.2.2 OpenFastTrace Free requirement tracking suite https://github.com/itsallcode/openfasttrace @@ -96,7 +96,6 @@ - 1.2.2 UTF-8 From c901bccf1578896f2ab8e4414dcb4fc60ca9ce17 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Fri, 14 Sep 2018 21:32:29 +0200 Subject: [PATCH 50/60] #170: Removed superfluous property switch in Maven call. --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b3bfe1cc..a448d8a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,9 +22,8 @@ before_install: - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- script: - - env - - echo $version - - mvn -Dproject.version=$version clean org.jacoco:jacoco-maven-plugin:prepare-agent install + - echo "Parsed the version $version from pom.xml" + - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install after_success: - codecov From ab62f4169d69f4472db299c8b14c16a6dcda0f72 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sun, 16 Sep 2018 13:14:53 +0200 Subject: [PATCH 51/60] #165: Origin location now rendered correctly in specification item and links. --- .../view/html/HtmlSpecificationItem.java | 21 ++- .../report/view/html/OriginLinkFormatter.java | 134 ++++++++++++++---- src/main/resources/css/report.css | 13 ++ .../openfasttrace/core/TestLocation.java | 2 +- .../view/html/TestHtmlSpecificationItem.java | 30 ++++ .../view/html/TestOriginLinkFormatter.java | 81 +++++++++-- 6 files changed, 229 insertions(+), 52 deletions(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java index f511b188..676dd72f 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java @@ -171,10 +171,13 @@ private String translateArtifactTypeCoverage(final LinkedSpecificationItem item) private void renderOrigin(final String indentation) { - this.stream.print(indentation); - this.stream.print("

"); - this.stream.print(OriginLinkFormatter.format(this.item.getLocation())); - this.stream.println("

"); + final String origin = OriginLinkFormatter.formatAsBlock(this.item.getLocation()); + if (!origin.isEmpty()) + { + this.stream.print(indentation); + this.stream.print(" "); + this.stream.println(origin); + } } private void renderLinks(final String indentation) @@ -242,9 +245,13 @@ protected void renderLinkEntry(final List outLinks, final String ind private void renderLinkOrigin(final TracedLink link) { - this.stream.print(" "); - this.stream.print(OriginLinkFormatter.format(link.getOtherLinkEnd().getLocation())); - this.stream.print(""); + final String origin = OriginLinkFormatter + .formatAsSpan(link.getOtherLinkEnd().getLocation()); + if (!origin.isEmpty()) + { + this.stream.print(" "); + this.stream.print(origin); + } } protected void renderEnd(final String indentation) diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java index ba232506..397f7362 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java @@ -1,5 +1,27 @@ package org.itsallcode.openfasttrace.report.view.html; +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; @@ -7,6 +29,9 @@ import org.itsallcode.openfasttrace.core.Location; +/** + * This class renders {@link Location} object as HTML spans or blocks. + */ public final class OriginLinkFormatter { private static final Pattern PROTOCOL_PREFIX_PATTERN = Pattern @@ -17,42 +42,53 @@ private OriginLinkFormatter() // prevent instantiation. } - public static String format(final Location location) + /** + * Render an origin to an HTML span + * + * @param location + * origin location + * @return a string representing an HTML span containing a link to the + * origin + */ + public static String formatAsSpan(final Location location) { - if (location == null) - { - return ""; - } - final String path = location.getPath(); - final StringBuilder builder = new StringBuilder(); - URI uri = null; - boolean validUri = false; - if (PROTOCOL_PREFIX_PATTERN.matcher(path).matches()) + return format(location, true); + } + + /** + * Render an origin to an HTML block + * + * @param location + * origin location + * @return a string representing an HTML block containing a link to the + * origin + */ + public static String formatAsBlock(final Location location) + { + return format(location, false); + } + + private static String format(final Location location, final boolean asSpan) + { + if ((location != null) && !location.getPath().isEmpty()) { - try - { - uri = URI.create(path); - validUri = true; - } - catch (final IllegalArgumentException e) - { - validUri = false; - } + return formatNonEmptyLocation(location, asSpan); } else { - final Path realPath = Paths.get(unWindowsify(path)); - if (realPath.isAbsolute()) - { - uri = realPath.toUri(); - validUri = true; - } - else - { - validUri = false; - } + return ""; } - if (validUri) + } + + private static String formatNonEmptyLocation(final Location location, final boolean asSpan) + { + final String path = location.getPath(); + final URI uri = checkPathHasProtocol(path) ? convertPathWithProtocolToUri(path) + : convertPathWithoutProtocolToUri(path); + final StringBuilder builder = new StringBuilder(); + builder.append(asSpan ? ""); + if (uri != null) { builder.append("" : "

"); return builder.toString(); } + private static boolean checkPathHasProtocol(final String path) + { + return PROTOCOL_PREFIX_PATTERN.matcher(path).matches(); + } + + private static URI convertPathWithProtocolToUri(final String path) + { + URI uri; + try + { + uri = URI.create(path); + } + catch (final IllegalArgumentException e) + { + uri = null; + } + return uri; + } + + private static URI convertPathWithoutProtocolToUri(final String path) + { + URI uri; + final Path realPath = Paths.get(unWindowsify(path)); + if (realPath.isAbsolute()) + { + uri = realPath.toUri(); + } + else + { + uri = null; + } + return uri; + } + private static String unWindowsify(final String path) { return path.replaceAll("([A-Z]:)", "/$1").replaceAll("\\\\", "/"); diff --git a/src/main/resources/css/report.css b/src/main/resources/css/report.css index a10dd10b..6754fd8e 100644 --- a/src/main/resources/css/report.css +++ b/src/main/resources/css/report.css @@ -119,3 +119,16 @@ summary .title { border-top: 1px solid lightgrey; font-family: courier; } + +.origin:before { + content: "\1F78B"; + margin: 0 0.5em; +} + +.origin { + font-family: courier; +} + +.sitem p.origin { + padding-left: 0.5em; +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/core/TestLocation.java b/src/test/java/org/itsallcode/openfasttrace/core/TestLocation.java index 21dbdef3..ede74e83 100644 --- a/src/test/java/org/itsallcode/openfasttrace/core/TestLocation.java +++ b/src/test/java/org/itsallcode/openfasttrace/core/TestLocation.java @@ -88,4 +88,4 @@ public void testIsNotCompleteEnoughWithoutPath() assertThat("builder with path set to null is complete", builderB.isCompleteEnough(), equalTo(false)); } -} +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java index a2317df9..0c56ebc8 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java @@ -170,6 +170,36 @@ public void testRenderIncomingLinks() ""); } + @Test + public void testRenderOutgoingLinks() + { + final SpecificationItem item = new SpecificationItem.Builder() // + .id(ITEM_A_ID) // + .build(); + final LinkedSpecificationItem linkedItem = new LinkedSpecificationItem(item); + linkedItem.addLinkToItemWithStatus(this.itemMockB, LinkStatus.COVERS); + linkedItem.addLinkToItemWithStatus(this.itemMockC, LinkStatus.UNWANTED); + final Viewable view = this.factory.createSpecificationItem(linkedItem); + view.render(0); + assertOutputLines( // + "
", // + "
", // + " " + CHECKMARK + + " name-a, rev. 1, dsn", // + "

" + ITEM_A_ID + "

", // + "
", // + "
", // + "
", // + ""); + } + @Test public void testRenderOrigin() { diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java index a36bc4d8..e8676252 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java @@ -1,7 +1,30 @@ package org.itsallcode.openfasttrace.report.view.html; +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + import static org.hamcrest.core.IsEqual.equalTo; -import static org.itsallcode.openfasttrace.report.view.html.OriginLinkFormatter.format; +import static org.itsallcode.openfasttrace.report.view.html.OriginLinkFormatter.formatAsBlock; +import static org.itsallcode.openfasttrace.report.view.html.OriginLinkFormatter.formatAsSpan; import static org.junit.Assert.assertThat; import org.itsallcode.openfasttrace.core.Location; @@ -9,44 +32,76 @@ public class TestOriginLinkFormatter { + @Test + public void testNullOrigin() + { + assertThat(formatAsSpan(null), equalTo("")); + } + + @Test + public void testEmptyOrigin() + { + assertThat(formatAsSpan(Location.create("", 1)), equalTo("")); + } + @Test public void testFormatMinimalHttpLink() { - assertThat(format(Location.create("http://example.org", 1)), - equalTo("http://example.org:1")); + assertPathAndLineRenderedToSpan("http://example.org", 1, + "http://example.org:1"); + } + + private void assertPathAndLineRenderedToSpan(final String path, final int line, + final String expected) + { + assertThat(formatAsSpan(Location.create(path, line)), + equalTo("" + expected + "")); + } + + @Test + public void testFormatMinimalHttpLinkAsBlock() + { + assertPathAndLineRenderedToBlock("http://example.org", 1, + "http://example.org:1"); + } + + private void assertPathAndLineRenderedToBlock(final String path, final int line, + final String expected) + { + assertThat(formatAsBlock(Location.create(path, line)), + equalTo("

" + expected + "

")); } @Test public void testLongerHttpLink() { - assertThat(format(Location.create("http://example.org/foo/bar%20baz?zoo", 1)), equalTo( - "http://example.org/foo/bar%20baz?zoo:1")); + assertPathAndLineRenderedToSpan("http://example.org/foo/bar%20baz?zoo", 1, + "http://example.org/foo/bar%20baz?zoo:1"); } @Test public void testFormatRegularAbsoluteUnixPath() { - assertThat(format(Location.create("/foo/bar/baz", 1111)), - equalTo("/foo/bar/baz:1111")); + assertPathAndLineRenderedToSpan("/foo/bar/baz", 1111, + "/foo/bar/baz:1111"); } @Test public void testFormatAbsoluteUnixPathWithSpecialCharacters() { - assertThat(format(Location.create("/fo o/bär/baz", 12345678)), - equalTo("/fo o/bär/baz:12345678")); + assertPathAndLineRenderedToSpan("/fo o/bär/baz", 12345678, + "/fo o/bär/baz:12345678"); } @Test public void testFormatRelativeUnixPath() { - assertThat(format(Location.create("foo/bar/baz", 2)), equalTo("foo/bar/baz:2")); + assertPathAndLineRenderedToSpan("foo/bar/baz", 2, "foo/bar/baz:2"); } @Test public void testIllegalUri() { - assertThat(format(Location.create("http://example.org/a b", 5)), - equalTo("http://example.org/a b:5")); + assertPathAndLineRenderedToSpan("http://example.org/a b", 5, "http://example.org/a b:5"); } -} \ No newline at end of file +} From 8c220018ef2eda78a435d7b79914941729e41b45 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sat, 29 Sep 2018 12:21:47 +0200 Subject: [PATCH 52/60] #165: Introduced parameter object for report settings. --- .../openfasttrace/ReportSettings.java | 161 ++++++++++++++++++ .../itsallcode/openfasttrace/Reporter.java | 46 ++--- .../cli/commands/TraceCommand.java | 19 ++- .../openfasttrace/mode/ReportMode.java | 46 ++--- .../openfasttrace/report/ReportService.java | 27 ++- .../openfasttrace/report/Reportable.java | 10 +- .../openfasttrace/report/html/HtmlReport.java | 10 +- .../report/plaintext/PlainTextReport.java | 54 +++--- .../openfasttrace/TestReportSettings.java | 94 ++++++++++ .../openfasttrace/mode/ITestReporter.java | 16 +- .../report/TestReportService.java | 22 ++- .../report/html/TestHtmlReport.java | 3 +- .../report/plaintext/TestPlainTextReport.java | 12 +- 13 files changed, 385 insertions(+), 135 deletions(-) create mode 100644 src/main/java/org/itsallcode/openfasttrace/ReportSettings.java create mode 100644 src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java diff --git a/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java new file mode 100644 index 00000000..02024e58 --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java @@ -0,0 +1,161 @@ +package org.itsallcode.openfasttrace; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import org.itsallcode.openfasttrace.core.Newline; +import org.itsallcode.openfasttrace.report.ReportConstants; +import org.itsallcode.openfasttrace.report.ReportVerbosity; + +/** + * This class implements a parameter object to control the settings of OFT's + * report mode. + */ +public class ReportSettings +{ + private final ReportVerbosity verbosity; + private final boolean showOrigin; + private final String outputFormat; + private final Newline newlineFormat; + + private ReportSettings(final Builder builder) + { + this.verbosity = builder.verbosity; + this.showOrigin = builder.showOrigin; + this.outputFormat = builder.outputFormat; + this.newlineFormat = builder.newlineFormat; + } + + /** + * Get the report verbosity + * + * @return report verbosity + */ + public ReportVerbosity getReportVerbosity() + { + return this.verbosity; + } + + /** + * Should the origin of a specification item be shown in the report? + * + * @return true if the origin should be shown + */ + public boolean showOrigin() + { + return this.showOrigin; + } + + /** + * Get the report output format (e.g. "plain" or "html") + * + * @return report output format + */ + public String getOutputFormat() + { + return this.outputFormat; + } + + /** + * Get the newline format + * + * @return newline format + */ + public Newline getNewlineFormat() + { + return this.newlineFormat; + } + + /** + * Builder for {@link ReportSettings} + */ + public static class Builder + { + public Newline newlineFormat = Newline.UNIX; + public String outputFormat = ReportConstants.DEFAULT_REPORT_FORMAT; + public boolean showOrigin = false; + ReportVerbosity verbosity = ReportVerbosity.FAILURE_DETAILS; + + /** + * Create a new instance of {@link ReportSettings} + * + * @return + */ + public ReportSettings build() + { + return new ReportSettings(this); + } + + /** + * Set the report verbosity + * + * @param verbosity + * report verbosity + * @return this for fluent programming + */ + public Builder verbosity(final ReportVerbosity verbosity) + { + this.verbosity = verbosity; + return this; + } + + /** + * Set the whether the origin of specification items should be shown in + * the report + * + * @param showOrign + * set to true if the origin should be shown + * @return this for fluent programming + */ + public Builder showOrigin(final boolean showOrigin) + { + this.showOrigin = showOrigin; + return this; + } + + /** + * Set the output format + * + * @param outputFormat + * output format + * @return this for fluent programming + */ + public Builder outputFormat(final String outputFormat) + { + this.outputFormat = outputFormat; + return this; + } + + /** + * Set the newline format + * + * @param newlineFormat + * newline format + * @return this for fluent programming + */ + public Builder newlineFormat(final Newline newlineFormat) + { + this.newlineFormat = newlineFormat; + return this; + } + } +} diff --git a/src/main/java/org/itsallcode/openfasttrace/Reporter.java b/src/main/java/org/itsallcode/openfasttrace/Reporter.java index f811acb7..a826e4cb 100644 --- a/src/main/java/org/itsallcode/openfasttrace/Reporter.java +++ b/src/main/java/org/itsallcode/openfasttrace/Reporter.java @@ -26,10 +26,8 @@ import java.nio.file.Path; import java.util.List; -import org.itsallcode.openfasttrace.core.Newline; import org.itsallcode.openfasttrace.core.Trace; import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; -import org.itsallcode.openfasttrace.report.ReportVerbosity; /** * OFT requirements tracer @@ -62,24 +60,6 @@ public interface Reporter */ public Reporter setFilters(FilterSettings filterSettings); - /** - * Set the representation for new line - * - * @param newline - * type of newline - * @return a Reporter instance for fluent programming - */ - public Reporter setNewline(Newline newline); - - /** - * Select how verbose the tracing stream should be - * - * @param verbosity - * stream verbosity - * @return a Reporter instance for fluent programming - */ - public Reporter setReportVerbosity(final ReportVerbosity verbosity); - /** * Set the {@link TagImporterConfig} for the * {@link LegacyTagImporterFactory}. @@ -91,14 +71,16 @@ public interface Reporter public Reporter setLegacyTagImporterPathConfig(final TagImporterConfig config); /** - * Set whether the report should show origin information (e.g. file and line - * number) for specification items + * Configure the report settings * - * @param showOrigin - * true if origin information should be shown + * @param settings + * report settings * @return a Reporter instance for fluent programming + * + * @see {@link ReportSettings.Builder} for a list of available configuration + * options */ - public Reporter setShowOrigin(final boolean showOrigin); + public Reporter configureReport(ReportSettings settings); /** * Run a trace on the input files @@ -113,22 +95,14 @@ public interface Reporter * * @param output * output file or directory - * - * @param format - * stream format (this is a name defined in the respective - * reporter plug-in) */ - public void reportToFileInFormat(final Trace trace, final Path output, final String format); + public void reportToFile(final Trace trace, final Path output); /** * Write the tracing stream to standard out * * @param trace * trace result to be written - * - * @param format - * stream format (this is a name defined in the respective - * reporter plug-in) */ - public void reportToStdOutInFormat(final Trace trace, final String format); -} + public void reportToStdOut(final Trace trace); +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java index 3c565789..764bd9a0 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java @@ -25,6 +25,7 @@ import java.nio.file.Path; +import org.itsallcode.openfasttrace.ReportSettings; import org.itsallcode.openfasttrace.Reporter; import org.itsallcode.openfasttrace.cli.CliArguments; import org.itsallcode.openfasttrace.core.Trace; @@ -58,27 +59,33 @@ public boolean run() private Reporter createReporter() { + final ReportSettings settings = convertCommandLineArgumentsToReportSettings(); final Reporter reporter = new ReportMode(); reporter.addInputs(toPaths(this.arguments.getInputs())) // .setFilters(createFilterSettingsFromArguments()) // - .setNewline(this.arguments.getNewline()) // - .setReportVerbosity(this.arguments.getReportVerbosity()) // - .setShowOrigin(this.arguments.getShowOrigin()); + .configureReport(settings); return reporter; } + private ReportSettings convertCommandLineArgumentsToReportSettings() + { + return new ReportSettings.Builder() + .verbosity(this.arguments.getReportVerbosity()) + .newlineFormat(this.arguments.getNewline()) + .showOrigin(this.arguments.getShowOrigin()).build(); + } + private Trace report(final Reporter reporter) { final Trace trace = reporter.trace(); final Path outputPath = this.arguments.getOutputPath(); if (null == outputPath) { - reporter.reportToStdOutInFormat(trace, this.arguments.getOutputFormat()); + reporter.reportToStdOut(trace); } else { - reporter.reportToFileInFormat(trace, this.arguments.getOutputPath(), - this.arguments.getOutputFormat()); + reporter.reportToFile(trace, this.arguments.getOutputPath()); } return trace; } diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java index c92f0101..6c3221f7 100644 --- a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java +++ b/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java @@ -25,53 +25,61 @@ import java.nio.file.Path; import java.util.List; +import org.itsallcode.openfasttrace.ReportSettings; import org.itsallcode.openfasttrace.Reporter; import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; import org.itsallcode.openfasttrace.core.Trace; import org.itsallcode.openfasttrace.core.Tracer; import org.itsallcode.openfasttrace.report.ReportService; -import org.itsallcode.openfasttrace.report.ReportVerbosity; public class ReportMode extends AbstractMode implements Reporter { private final Tracer tracer = new Tracer(); private final ReportService reportService = new ReportService(); - private ReportVerbosity verbosity = ReportVerbosity.FAILURE_DETAILS; - private boolean showOrigin; + private ReportSettings settings; - @Override - public Trace trace() + /** + * Create a new instance of a {@link ReportMode} using the default report + * settings. + */ + public ReportMode() { - final List linkedItems = importLinkedSpecificationItems(); - return this.tracer.trace(linkedItems); + this(new ReportSettings.Builder().build()); } - @Override - public void reportToFileInFormat(final Trace trace, final Path output, final String format) + /** + * Create a new instance of a {@link ReportMode} using the custom report + * settings. + */ + public ReportMode(final ReportSettings settings) { - this.reportService.reportTraceToPath(trace, output, format, this.verbosity, this.newline, - this.showOrigin); + this.settings = settings; } @Override - public Reporter setReportVerbosity(final ReportVerbosity verbosity) + public Reporter configureReport(final ReportSettings settings) { - this.verbosity = verbosity; + this.settings = settings; return this; } @Override - public void reportToStdOutInFormat(final Trace trace, final String format) + public Trace trace() { - this.reportService.reportTraceToStdOut(trace, format, this.verbosity, this.newline, - this.showOrigin); + final List linkedItems = importLinkedSpecificationItems(); + return this.tracer.trace(linkedItems); } @Override - public Reporter setShowOrigin(final boolean showOrigin) + public void reportToFile(final Trace trace, final Path output) { - this.showOrigin = showOrigin; - return this; + this.reportService.reportTraceToPath(trace, output, this.settings); + } + + @Override + public void reportToStdOut(final Trace trace) + { + this.reportService.reportTraceToStdOut(trace, this.settings); } @Override diff --git a/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java b/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java index 860e21f1..4006d9d2 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java @@ -25,19 +25,19 @@ import java.nio.file.Files; import java.nio.file.Path; -import org.itsallcode.openfasttrace.core.Newline; +import org.itsallcode.openfasttrace.ReportSettings; import org.itsallcode.openfasttrace.core.Trace; import org.itsallcode.openfasttrace.report.html.HtmlReport; import org.itsallcode.openfasttrace.report.plaintext.PlainTextReport; public class ReportService { - public void reportTraceToPath(final Trace trace, final Path outputPath, final String format, - final ReportVerbosity verbosity, final Newline newline, final boolean showOrigin) + public void reportTraceToPath(final Trace trace, final Path outputPath, + final ReportSettings settings) { try (OutputStream outputStream = Files.newOutputStream(outputPath)) { - reportTraceToStream(trace, format, verbosity, newline, outputStream, showOrigin); + reportTraceToStream(trace, outputStream, settings); } catch (final IOException e) { @@ -45,10 +45,9 @@ public void reportTraceToPath(final Trace trace, final Path outputPath, final St } } - public void reportTraceToStdOut(final Trace trace, final String format, - final ReportVerbosity verbosity, final Newline newline, final boolean showOrigin) + public void reportTraceToStdOut(final Trace trace, final ReportSettings settings) { - reportTraceToStream(trace, format, verbosity, newline, getStdOutStream(), showOrigin); + reportTraceToStream(trace, getStdOutStream(), settings); } // Using System.out by intention @@ -58,13 +57,12 @@ private PrintStream getStdOutStream() return System.out; } - private void reportTraceToStream(final Trace trace, final String format, - final ReportVerbosity verbosity, final Newline newline, final OutputStream outputStream, - final boolean showOrigin) + private void reportTraceToStream(final Trace trace, final OutputStream outputStream, + final ReportSettings settings) { final OutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); - final Reportable report = createReport(trace, format, newline); - report.renderToStreamWithVerbosityLevel(bufferedOutputStream, verbosity, showOrigin); + final Reportable report = createReport(trace, settings); + report.renderToStream(bufferedOutputStream); try { bufferedOutputStream.flush(); @@ -75,13 +73,14 @@ private void reportTraceToStream(final Trace trace, final String format, } } - protected Reportable createReport(final Trace trace, final String format, final Newline newline) + protected Reportable createReport(final Trace trace, final ReportSettings settings) { Reportable report = null; + final String format = settings.getOutputFormat(); switch (ReportFormat.parse(format)) { case PLAIN_TEXT: - report = new PlainTextReport(trace, newline); + report = new PlainTextReport(trace, settings); break; case HTML: report = new HtmlReport(trace); diff --git a/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java b/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java index 265c9c71..7520f086 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java @@ -34,13 +34,7 @@ public interface Reportable * Render the plain text coverage stream. * * @param outputStream - * the output stream to which the stream is rendered - * @param verbosity - * the level of detail that is reported - * @param showOrigin - * true if the report should contain origin - * information (e.g file and line number) + * output stream to which the stream is rendered */ - public void renderToStreamWithVerbosityLevel(OutputStream outputStream, - ReportVerbosity verbosity, boolean showOrigin); + public void renderToStream(final OutputStream outputStream); } diff --git a/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java b/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java index f3125a5c..2542cb12 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java @@ -29,7 +29,6 @@ import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; import org.itsallcode.openfasttrace.core.Trace; -import org.itsallcode.openfasttrace.report.ReportVerbosity; import org.itsallcode.openfasttrace.report.Reportable; import org.itsallcode.openfasttrace.report.view.ViewFactory; import org.itsallcode.openfasttrace.report.view.Viewable; @@ -41,6 +40,12 @@ public class HtmlReport implements Reportable private final Trace trace; private static final String REPORT_CSS_FILE = "/css/report.css"; + /** + * Create a new instance of an {@link HtmlReport} + * + * @param trace + * trace to be reported on + */ public HtmlReport(final Trace trace) { this.trace = trace; @@ -57,8 +62,7 @@ public static URL getCssUrl() } @Override - public void renderToStreamWithVerbosityLevel(final OutputStream outputStream, - final ReportVerbosity verbosity, final boolean showOrigin) + public void renderToStream(final OutputStream outputStream) { final ViewFactory factory = HtmlViewFactory.create(outputStream, getCssUrl()); final ViewableContainer view = factory.createView("", "Specification items by title"); diff --git a/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java b/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java index 40a03b92..ca888558 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java @@ -33,9 +33,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.itsallcode.openfasttrace.ReportSettings; import org.itsallcode.openfasttrace.core.*; import org.itsallcode.openfasttrace.report.ReportException; -import org.itsallcode.openfasttrace.report.ReportVerbosity; import org.itsallcode.openfasttrace.report.Reportable; /** @@ -47,32 +47,31 @@ public class PlainTextReport implements Reportable private final Trace trace; private static final Comparator LINKED_ITEM_BY_ID = Comparator .comparing(LinkedSpecificationItem::getId); - private final Newline newline; private int nonEmptySections = 0; + private final ReportSettings settings; /** * Create a new instance of {@link PlainTextReport} * * @param trace * the trace that will be reported. - * @param newline - * the newline format + * @param settings + * report settings */ // [impl->dsn~newline-format~1] - public PlainTextReport(final Trace trace, final Newline newline) + public PlainTextReport(final Trace trace, final ReportSettings settings) { this.trace = trace; - this.newline = newline; + this.settings = settings; } @Override - public void renderToStreamWithVerbosityLevel(final OutputStream outputStream, - final ReportVerbosity verbosity, final boolean showOrigin) + public void renderToStream(final OutputStream outputStream) { final Charset charset = StandardCharsets.UTF_8; try (final PrintStream report = new PrintStream(outputStream, false, charset.displayName())) { - renderToPrintStreamWithVerbosityLevel(report, verbosity, showOrigin); + renderToPrintStream(report); } catch (final UnsupportedEncodingException e) { @@ -80,10 +79,9 @@ public void renderToStreamWithVerbosityLevel(final OutputStream outputStream, } } - private void renderToPrintStreamWithVerbosityLevel(final PrintStream report, - final ReportVerbosity verbosity, final boolean showOrigin) + private void renderToPrintStream(final PrintStream report) { - switch (verbosity) + switch (this.settings.getReportVerbosity()) { case QUIET: break; @@ -102,18 +100,18 @@ private void renderToPrintStreamWithVerbosityLevel(final PrintStream report, renderSummary(report); break; case FAILURE_DETAILS: - renderFailureDetails(report, showOrigin); + renderFailureDetails(report, this.settings.showOrigin()); separateItemsFromSummary(report); renderSummary(report); break; case ALL: - renderAll(report, showOrigin); - report.print(this.newline); + renderAll(report, this.settings.showOrigin()); + report.print(this.settings.getNewlineFormat()); renderSummary(report); break; default: - throw new IllegalStateException( - "Unable to create stream for unknown verbosity level " + verbosity); + throw new IllegalStateException("Unable to create stream for unknown verbosity level " + + this.settings.getReportVerbosity()); } } @@ -121,14 +119,14 @@ private void separateItemsFromSummary(final PrintStream report) { if (this.trace.countDefects() > 0) { - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); } } private void renderResultStatus(final PrintStream report) { report.print(translateStatus(this.trace.hasNoDefects())); - report.print(this.newline.toString()); + report.print(this.settings.getNewlineFormat().toString()); } private String translateStatus(final boolean ok) @@ -149,7 +147,7 @@ private void renderSummary(final PrintStream report) report.print(this.trace.countDefects()); report.print(" defect"); } - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); } private void renderFailureIds(final PrintStream report) @@ -158,7 +156,7 @@ private void renderFailureIds(final PrintStream report) .sorted()// .forEachOrdered(id -> { report.print(id); - report.print(this.newline.toString()); + report.print(this.settings.getNewlineFormat().toString()); }); } @@ -180,7 +178,7 @@ private void renderItemSummary(final PrintStream report, final LinkedSpecificati report.print(" "); renderMaturity(report, item); report.print(translateArtifactTypeCoverage(item)); - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); } private String translateArtifactTypeCoverage(final LinkedSpecificationItem item) @@ -265,7 +263,7 @@ private void renderOrigin(final PrintStream report, final Location location) private void renderEmptyItemDetailsLine(final PrintStream report) { report.print("|"); - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); } private void renderDescription(final PrintStream report, final LinkedSpecificationItem item) @@ -278,7 +276,7 @@ private void renderDescription(final PrintStream report, final LinkedSpecificati { report.print("| "); report.print(line); - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); } ++this.nonEmptySections; } @@ -314,7 +312,7 @@ private void renderLink(final PrintStream report, final TracedLink link, report.print(status.getShortTag()); report.print(") "); report.print(link.getOtherLinkEnd().getId()); - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); if (showOrigin) { final Location location = link.getOtherLinkEnd().getLocation(); @@ -322,7 +320,7 @@ private void renderLink(final PrintStream report, final TracedLink link, { report.print("| "); renderOrigin(report, location); - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); } } } @@ -335,7 +333,7 @@ private void renderTags(final PrintStream report, final LinkedSpecificationItem renderEmptyItemDetailsLine(report); report.print("| #: "); report.print(tags.stream().collect(Collectors.joining(", "))); - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); ++this.nonEmptySections; } } @@ -351,7 +349,7 @@ private void renderOrigin(final PrintStream report, final LinkedSpecificationIte report.print(":"); report.print(location.getLine()); report.print(")"); - report.print(this.newline); + report.print(this.settings.getNewlineFormat()); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java new file mode 100644 index 00000000..2ae1b049 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java @@ -0,0 +1,94 @@ +package org.itsallcode.openfasttrace; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +import org.itsallcode.openfasttrace.ReportSettings.Builder; +import org.itsallcode.openfasttrace.core.Newline; +import org.itsallcode.openfasttrace.report.ReportVerbosity; +import org.junit.Before; +import org.junit.Test; + +public class TestReportSettings +{ + private Builder builder; + + @Before + public void before() + { + this.builder = new ReportSettings.Builder(); + } + + @Test + public void testDefaultVerbosity() + { + assertThat(this.builder.build().getReportVerbosity(), + equalTo(ReportVerbosity.FAILURE_DETAILS)); + } + + @Test + public void testOriginNotShownByDefault() + { + assertThat(this.builder.build().showOrigin(), equalTo(false)); + } + + @Test + public void testDefaultOutputFormat() + { + assertThat(this.builder.build().getOutputFormat(), equalTo("plain")); + } + + @Test + public void testDefaultNewlineFormat() + { + assertThat(this.builder.build().getNewlineFormat(), equalTo(Newline.UNIX)); + } + + @Test + public void testBuildWithVerbosity() + { + assertThat(this.builder.verbosity(ReportVerbosity.ALL).build().getReportVerbosity(), + equalTo(ReportVerbosity.ALL)); + } + + @Test + public void testBuildWithOriginShown() + { + assertThat(this.builder.showOrigin(true).build().showOrigin(), equalTo(true)); + } + + @Test + public void testBuildWithOutputFormat() + { + assertThat(this.builder.outputFormat("html").build().getOutputFormat(), equalTo("html")); + } + + @Test + public void testBuildWithNewlineFormat() + { + assertThat(this.builder.newlineFormat(Newline.OLDMAC).build().getNewlineFormat(), + equalTo(Newline.OLDMAC)); + } +} diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java index e2a22bf6..e5899a34 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java @@ -34,10 +34,10 @@ import java.util.Set; import org.itsallcode.openfasttrace.FilterSettings; +import org.itsallcode.openfasttrace.ReportSettings; import org.itsallcode.openfasttrace.Reporter; import org.itsallcode.openfasttrace.core.Newline; import org.itsallcode.openfasttrace.core.Trace; -import org.itsallcode.openfasttrace.report.ReportConstants; import org.itsallcode.openfasttrace.report.ReportVerbosity; import org.junit.Before; import org.junit.Test; @@ -64,8 +64,7 @@ public void testTraceToFile() throws IOException private void writePlainTextReportFromTrace(final Trace trace) { - this.reporter.reportToFileInFormat(trace, this.outputFile, - ReportConstants.DEFAULT_REPORT_FORMAT); + this.reporter.reportToFile(trace, this.outputFile); } private void assertStandardReportFileResult() throws IOException @@ -77,8 +76,10 @@ private void assertStandardReportFileResult() throws IOException @Test public void testTraceWithReportVerbosityMinimal() throws IOException { + final ReportSettings settings = new ReportSettings.Builder() + .verbosity(ReportVerbosity.MINIMAL).build(); final Trace trace = this.reporter.addInputs(this.docDir) // - .setReportVerbosity(ReportVerbosity.MINIMAL) // + .configureReport(settings) // .trace(); writePlainTextReportFromTrace(trace); assertOutputFileExists(true); @@ -88,8 +89,11 @@ public void testTraceWithReportVerbosityMinimal() throws IOException @Test public void testTraceMacNewlines() throws IOException { + final ReportSettings settings = new ReportSettings.Builder() // + .newlineFormat(Newline.OLDMAC) // + .build(); final Trace trace = this.reporter.addInputs(this.docDir) // - .setNewline(Newline.OLDMAC) // + .configureReport(settings) // .trace(); writePlainTextReportFromTrace(trace); assertThat(Files.exists(this.outputFile), equalTo(true)); @@ -104,7 +108,7 @@ public void testTraceToStdOut() throws IOException { final Trace trace = this.reporter.addInputs(this.docDir) // .trace(); - this.reporter.reportToStdOutInFormat(trace, ReportConstants.DEFAULT_REPORT_FORMAT); + this.reporter.reportToStdOut(trace); assertStandardReportStdOutResult(); } diff --git a/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java b/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java index 1592b3a1..163e646c 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java @@ -29,7 +29,7 @@ import java.io.File; import java.io.IOException; -import org.itsallcode.openfasttrace.core.Newline; +import org.itsallcode.openfasttrace.ReportSettings; import org.itsallcode.openfasttrace.core.Trace; import org.junit.Before; import org.junit.Rule; @@ -61,24 +61,27 @@ public void prepareTest() @Test public void testReportPlainText() { - this.service.reportTraceToStdOut(this.traceMock, "plain", ReportVerbosity.MINIMAL, - Newline.UNIX, false); + final ReportSettings settings = new ReportSettings.Builder() + .verbosity(ReportVerbosity.MINIMAL).build(); + this.service.reportTraceToStdOut(this.traceMock, settings); assertThat(this.systemOutRule.getLog(), equalTo("not ok\n")); } @Test public void testReportHtml() { - this.service.reportTraceToStdOut(this.traceMock, "html", ReportVerbosity.MINIMAL, - Newline.UNIX, false); + final ReportSettings settings = new ReportSettings.Builder().outputFormat("html") + .verbosity(ReportVerbosity.MINIMAL).build(); + this.service.reportTraceToStdOut(this.traceMock, settings); assertThat(this.systemOutRule.getLog(), startsWith("")); } @Test(expected = IllegalArgumentException.class) public void testInvalidReportFormatThrowsIllegalArgumentException() { - this.service.reportTraceToStdOut(this.traceMock, "invalid", ReportVerbosity.QUIET, - Newline.UNIX, false); + final ReportSettings settings = new ReportSettings.Builder().outputFormat("invalid") + .verbosity(ReportVerbosity.QUIET).build(); + this.service.reportTraceToStdOut(this.traceMock, settings); } @Test(expected = ReportException.class) @@ -86,7 +89,8 @@ public void testReportToIllegalPathThrowsReportExpection() throws IOException { final File readOnlyFile = this.temporaryFolder.newFile(); readOnlyFile.setReadOnly(); - this.service.reportTraceToPath(this.traceMock, readOnlyFile.toPath(), "plain", - ReportVerbosity.QUIET, Newline.UNIX, false); + final ReportSettings settings = new ReportSettings.Builder() + .verbosity(ReportVerbosity.QUIET).build(); + this.service.reportTraceToPath(this.traceMock, readOnlyFile.toPath(), settings); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java index 07721e2b..95ee2dd0 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java @@ -31,7 +31,6 @@ import java.util.Arrays; import org.itsallcode.openfasttrace.core.*; -import org.itsallcode.openfasttrace.report.ReportVerbosity; import org.itsallcode.openfasttrace.report.Reportable; import org.junit.Before; import org.junit.Test; @@ -62,7 +61,7 @@ protected String renderToString() { final OutputStream outputStream = new ByteArrayOutputStream(); final Reportable report = new HtmlReport(this.traceMock); - report.renderToStreamWithVerbosityLevel(outputStream, ReportVerbosity.ALL, false); + report.renderToStream(outputStream); final String outputAsString = outputStream.toString(); return outputAsString; } diff --git a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java index d3d2ceab..97f162f3 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java @@ -37,6 +37,7 @@ import java.io.OutputStream; import java.util.*; +import org.itsallcode.openfasttrace.ReportSettings; import org.itsallcode.openfasttrace.core.*; import org.itsallcode.openfasttrace.report.ReportVerbosity; import org.itsallcode.openfasttrace.report.Reportable; @@ -62,8 +63,9 @@ public void prepareTest() public void testOutputStreamClosed() throws IOException { final OutputStream outputStreamMock = mock(OutputStream.class); - new PlainTextReport(this.traceMock, NEWLINE_SEPARATOR) - .renderToStreamWithVerbosityLevel(outputStreamMock, ReportVerbosity.SUMMARY, false); + final ReportSettings settings = new ReportSettings.Builder() + .verbosity(ReportVerbosity.SUMMARY).build(); + new PlainTextReport(this.traceMock, settings).renderToStream(outputStreamMock); verify(outputStreamMock).close(); } @@ -115,8 +117,10 @@ private String getReportOutputWithNewline(final ReportVerbosity verbosity, final Newline newline, final boolean showOrigin) { final OutputStream outputStream = new ByteArrayOutputStream(); - final Reportable report = new PlainTextReport(this.traceMock, newline); - report.renderToStreamWithVerbosityLevel(outputStream, verbosity, showOrigin); + final ReportSettings settings = new ReportSettings.Builder().verbosity(verbosity) + .newlineFormat(newline).showOrigin(showOrigin).build(); + final Reportable report = new PlainTextReport(this.traceMock, settings); + report.renderToStream(outputStream); return outputStream.toString(); } From ef99a2fef5b5f98a94bfe7609c22db189401ebd8 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sun, 7 Oct 2018 19:19:39 +0200 Subject: [PATCH 53/60] #165: Refactoring to the point where Report unit tests are running again. --- .../itsallcode/openfasttrace/Converter.java | 93 ----------- .../openfasttrace/ExportSettings.java | 107 ++++++++++++ .../openfasttrace/ImportSettings.java | 116 +++++++++++++ .../org/itsallcode/openfasttrace/Oft.java | 155 ++++++++++++++++++ .../openfasttrace/ReportSettings.java | 28 +++- .../itsallcode/openfasttrace/Reporter.java | 108 ------------ .../cli/commands/ConvertCommand.java | 12 +- .../cli/commands/TraceCommand.java | 16 +- .../openfasttrace/core/OftRunner.java | 111 +++++++++++++ .../importer/ImporterContext.java | 16 +- .../importer/ImporterService.java | 34 ++-- .../importer/tag/TagImporterFactory.java | 6 +- .../tag/config/TagImporterConfig.java | 59 ------- .../openfasttrace/mode/AbstractMode.java | 6 +- .../openfasttrace/mode/ConvertMode.java | 6 +- .../openfasttrace/mode/ReportMode.java | 6 +- .../report/plaintext/PlainTextReport.java | 24 +-- .../openfasttrace/TestExportSettings.java | 72 ++++++++ .../openfasttrace/TestImportSettings.java | 77 +++++++++ .../openfasttrace/TestReportSettings.java | 8 +- .../importer/ImporterFactoryTestBase.java | 4 +- .../importer/TestImporterContext.java | 4 +- .../tag/TestTagImporterFactoryWithConfig.java | 12 +- .../mode/AbstractOftModeTest.java | 8 +- .../openfasttrace/mode/ITestConverter.java | 6 +- ...tReporter.java => ITestOftAsReporter.java} | 75 +++++---- .../mode/ITestReporterWithFilter.java | 4 +- .../report/plaintext/TestPlainTextReport.java | 2 +- 28 files changed, 781 insertions(+), 394 deletions(-) delete mode 100644 src/main/java/org/itsallcode/openfasttrace/Converter.java create mode 100644 src/main/java/org/itsallcode/openfasttrace/ExportSettings.java create mode 100644 src/main/java/org/itsallcode/openfasttrace/ImportSettings.java create mode 100644 src/main/java/org/itsallcode/openfasttrace/Oft.java delete mode 100644 src/main/java/org/itsallcode/openfasttrace/Reporter.java create mode 100644 src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java delete mode 100644 src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java create mode 100644 src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java create mode 100644 src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java rename src/test/java/org/itsallcode/openfasttrace/mode/{ITestReporter.java => ITestOftAsReporter.java} (63%) diff --git a/src/main/java/org/itsallcode/openfasttrace/Converter.java b/src/main/java/org/itsallcode/openfasttrace/Converter.java deleted file mode 100644 index 2a23bc29..00000000 --- a/src/main/java/org/itsallcode/openfasttrace/Converter.java +++ /dev/null @@ -1,93 +0,0 @@ - -package org.itsallcode.openfasttrace; - -/*- - * #%L - \* OpenFastTrace - * %% - * Copyright (C) 2016 - 2017 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import java.nio.file.Path; -import java.util.List; - -import org.itsallcode.openfasttrace.core.Newline; -import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; - -/** - * Convert between different requirements formats (e.g. from ReqM2 to Markdown) - */ -public interface Converter -{ - /** - * Select one or more input files - * - * @param inputs - * input files - * @return a Converter instance for fluent programming - */ - public Converter addInputs(final Path... inputs); - - /** - * Select one or more input files - * - * @param inputs - * input files - * @return a Converter instance for fluent programming - */ - public Converter addInputs(final List inputs); - - /** - * Set the filters to be applied during conversion - * - * @param filterSettings - * the filter settings - */ - public Converter setFilters(FilterSettings filterSettings); - - /** - * Set the representation for new line - * - * @param newline - * type of newline - * @return a Converter instance for fluent programming - */ - public Converter setNewline(Newline newline); - - /** - * Set the {@link TagImporterConfig} for the - * {@link LegacyTagImporterFactory}. - * - * @param config - * the {@link TagImporterConfig} to set. - * @return a Converter instance for fluent programming - */ - public Converter setLegacyTagImporterPathConfig(final TagImporterConfig config); - - /** - * Convert the collected requirements into target requirement format - * - * @param output - * output file - * - * @param format - * target format (this is a name defined in the respective - * exporter plug-in) - */ - public void convertToFileInFormat(final Path output, final String format); -} diff --git a/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java new file mode 100644 index 00000000..7482a406 --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java @@ -0,0 +1,107 @@ +package org.itsallcode.openfasttrace; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import org.itsallcode.openfasttrace.core.Newline; +import org.itsallcode.openfasttrace.exporter.ExporterConstants; + +/** + * This class implements a parameter object to control the settings of OFT's + * export mode. + */ +public class ExportSettings +{ + private final String outputFormat; + private final Newline newline; + + private ExportSettings(final Builder builder) + { + this.outputFormat = builder.outputFormat; + this.newline = builder.newline; + } + + /** + * Get the conversion output format + * + * @return output format + */ + public String getOutputFormat() + { + return this.outputFormat; + } + + /** + * Get the newline format used in the conversion results + * + * @return newline format + */ + public Newline getNewline() + { + return this.newline; + } + + /** + * Builder for {@link ExportSettings} + */ + public static class Builder + { + private String outputFormat = ExporterConstants.DEFAULT_OUTPUT_FORMAT; + private Newline newline = Newline.UNIX; + + /** + * Set the converter output format + * + * @param outputFormat + * output format + * @return this for fluent programming + */ + public Builder outputFormat(final String outputFormat) + { + this.outputFormat = outputFormat; + return this; + } + + /** + * Get the newline format to be used in the conversion result + * + * @param newline + * newline format + * @return this for fluent programming + */ + public Builder newline(final Newline newline) + { + this.newline = newline; + return this; + } + + /** + * Create a new instance of {@link ExportSettings} + * + * @return new instance + */ + public ExportSettings build() + { + return new ExportSettings(this); + } + } +} diff --git a/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java new file mode 100644 index 00000000..a68c595c --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java @@ -0,0 +1,116 @@ +package org.itsallcode.openfasttrace; + +import java.util.ArrayList; +import java.util.List; + +import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +public class ImportSettings +{ + private final FilterSettings filter; + private final List pathConfigs; + + protected ImportSettings(final Builder builder) + { + this.filter = builder.filter; + this.pathConfigs = builder.pathConfigs; + } + + /** + * Get the filter settings + * + * @return filter settings + */ + public FilterSettings getFilters() + { + return this.filter; + } + + /** + * Get path configurations. Those are per-path settings that define how the + * importer should interpret the specification item tags it found. + * + * @return path configurations + */ + public List getPathConfigs() + { + return this.pathConfigs; + } + + /** + * Create a the default import settings + * + * @return default import settings + */ + public static ImportSettings createDefault() + { + return new Builder().build(); + } + + /** + * Builder for {@link ImportSettings} + */ + public static class Builder + { + private FilterSettings filter = FilterSettings.createAllowingEverything(); + private List pathConfigs = new ArrayList<>(); + + /** + * Set the filters to be used during import + * + * @param filter + * filter settings + * @return this for fluent programming + */ + public Builder filter(final FilterSettings filter) + { + this.filter = filter; + return this; + } + + /** + * Set path configurations + * + * @param pathConfigs + * per-path importer configurations + * @return this for fluent programming + */ + public Builder pathConfigs(final List pathConfigs) + { + this.pathConfigs = pathConfigs; + return this; + } + + /** + * Create a new instance of {@link ImportSettings} + * + * @return import settings instance + */ + public ImportSettings build() + { + return new ImportSettings(this); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/Oft.java b/src/main/java/org/itsallcode/openfasttrace/Oft.java new file mode 100644 index 00000000..503070e6 --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/Oft.java @@ -0,0 +1,155 @@ + +package org.itsallcode.openfasttrace; + +/*- + * #%L + \* OpenFastTrace + * %% + * Copyright (C) 2016 - 2017 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import java.nio.file.Path; +import java.util.List; + +import org.itsallcode.openfasttrace.core.*; + +/** + * Import requirements (e.g. from ReqM2 to Markdown) + */ +public interface Oft +{ + /** + * Select one or more input files + * + * @param inputs + * input files + * @return a Converter instance for fluent programming + */ + public Oft addInputs(final Path... inputs); + + /** + * Select one or more input files + * + * @param inputs + * input files + * @return an {@link Oft} instance for fluent programming + */ + public Oft addInputs(final List inputs); + + /** + * Run an import with default settings + * + * @return list of imported specification items + */ + public List importItems(); + + /** + * Run an import + * + * @param settings + * import stage settings + * + * @return list of imported specification items. + */ + public List importItems(ImportSettings settings); + + /** + * Link specification items + * + * @param items + * specification items to be interlinked + * @return list of linked specification items + */ + public List link(List items); + + /** + * Trace a list of linked specification items + * + * @param linkedItems + * items to be traced + * @return trace result + */ + public Trace trace(List linkedItems); + + /** + * Export items with default settings + */ + public void export(List items); + + /** + * Export items + * + * @param settings + * export settings + */ + public void export(List items, ExportSettings settings); + + /** + * Generate a report with default settings + */ + public void report(Trace trace); + + /** + * Generate a report + * + * @param trace + * specification item trace to be turned into a report + * + * @param settings + * report settings + */ + public void report(Trace trace, ReportSettings settings); + + /** + * Generate a report + * + * @param trace + * specification item trace to be turned into a report + * + * @param outputPath + * path the report should be written to (or file in case this is + * a single-file report) + * + * @param settings + * report settings + */ + public void reportToPath(Trace trace, Path outputPath); + + /** + * Generate a report + * + * @param trace + * specification item trace to be turned into a report + * + * @param outputPath + * path the report should be written to (or file in case this is + * a single-file report) + * + * @param settings + * report settings + */ + public void reportToPath(Trace trace, Path outputPath, ReportSettings settings); + + /** + * Create a new instance of a object implementing the {@link Oft} interface + */ + public static Oft create() + { + return new OftRunner(); + } +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java index 02024e58..c3379a39 100644 --- a/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java +++ b/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java @@ -35,14 +35,14 @@ public class ReportSettings private final ReportVerbosity verbosity; private final boolean showOrigin; private final String outputFormat; - private final Newline newlineFormat; + private final Newline newline; private ReportSettings(final Builder builder) { this.verbosity = builder.verbosity; this.showOrigin = builder.showOrigin; this.outputFormat = builder.outputFormat; - this.newlineFormat = builder.newlineFormat; + this.newline = builder.newline; } /** @@ -80,9 +80,19 @@ public String getOutputFormat() * * @return newline format */ - public Newline getNewlineFormat() + public Newline getNewline() { - return this.newlineFormat; + return this.newline; + } + + /** + * Create default report settings + * + * @return default settings + */ + public static ReportSettings createDefault() + { + return new Builder().build(); } /** @@ -90,7 +100,7 @@ public Newline getNewlineFormat() */ public static class Builder { - public Newline newlineFormat = Newline.UNIX; + public Newline newline = Newline.UNIX; public String outputFormat = ReportConstants.DEFAULT_REPORT_FORMAT; public boolean showOrigin = false; ReportVerbosity verbosity = ReportVerbosity.FAILURE_DETAILS; @@ -148,14 +158,14 @@ public Builder outputFormat(final String outputFormat) /** * Set the newline format * - * @param newlineFormat + * @param newline * newline format * @return this for fluent programming */ - public Builder newlineFormat(final Newline newlineFormat) + public Builder newline(final Newline newline) { - this.newlineFormat = newlineFormat; + this.newline = newline; return this; } } -} +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/Reporter.java b/src/main/java/org/itsallcode/openfasttrace/Reporter.java deleted file mode 100644 index a826e4cb..00000000 --- a/src/main/java/org/itsallcode/openfasttrace/Reporter.java +++ /dev/null @@ -1,108 +0,0 @@ - -package org.itsallcode.openfasttrace; - -/*- - * #%L - \* OpenFastTrace - * %% - * Copyright (C) 2016 - 2017 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import java.nio.file.Path; -import java.util.List; - -import org.itsallcode.openfasttrace.core.Trace; -import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; - -/** - * OFT requirements tracer - */ -public interface Reporter -{ - /** - * Select one or more input files - * - * @param inputs - * input files - * @return a Reporter instance for fluent programming - */ - public Reporter addInputs(final Path... inputs); - - /** - * Select one or more input files - * - * @param inputs - * input files - * @return a Reporter instance for fluent programming - */ - public Reporter addInputs(final List inputs); - - /** - * Set the filters to be applied during conversion - * - * @param filterSettings - * the filter settings - */ - public Reporter setFilters(FilterSettings filterSettings); - - /** - * Set the {@link TagImporterConfig} for the - * {@link LegacyTagImporterFactory}. - * - * @param config - * the {@link TagImporterConfig} to set. - * @return a Reporter instance for fluent programming - */ - public Reporter setLegacyTagImporterPathConfig(final TagImporterConfig config); - - /** - * Configure the report settings - * - * @param settings - * report settings - * @return a Reporter instance for fluent programming - * - * @see {@link ReportSettings.Builder} for a list of available configuration - * options - */ - public Reporter configureReport(ReportSettings settings); - - /** - * Run a trace on the input files - */ - public Trace trace(); - - /** - * Write the tracing stream to a file - * - * @param trace - * trace result to be written - * - * @param output - * output file or directory - */ - public void reportToFile(final Trace trace, final Path output); - - /** - * Write the tracing stream to standard out - * - * @param trace - * trace result to be written - */ - public void reportToStdOut(final Trace trace); -} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java index 7d170038..73bcb603 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java @@ -25,7 +25,7 @@ import java.nio.file.Path; -import org.itsallcode.openfasttrace.Converter; +import org.itsallcode.openfasttrace.Export; import org.itsallcode.openfasttrace.cli.CliArguments; import org.itsallcode.openfasttrace.mode.ConvertMode; @@ -50,23 +50,23 @@ public ConvertCommand(final CliArguments arguments) @Override public boolean run() { - final Converter converter = createConverter(); + final Export converter = createConverter(); convert(converter); return true; } - private Converter createConverter() + private Export createConverter() { - final Converter converter = new ConvertMode(); + final Export converter = new ConvertMode(); converter.addInputs(toPaths(this.arguments.getInputs())) // .setFilters(createFilterSettingsFromArguments()) // .setNewline(this.arguments.getNewline()); return converter; } - private void convert(final Converter converter) + private void convert(final Export converter) { final Path outputPath = this.arguments.getOutputPath(); - converter.convertToFileInFormat(outputPath, this.arguments.getOutputFormat()); + converter.exportToFileInFormat(outputPath, this.arguments.getOutputFormat()); } } diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java index 764bd9a0..9069feaf 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java @@ -26,7 +26,7 @@ import java.nio.file.Path; import org.itsallcode.openfasttrace.ReportSettings; -import org.itsallcode.openfasttrace.Reporter; +import org.itsallcode.openfasttrace.Report; import org.itsallcode.openfasttrace.cli.CliArguments; import org.itsallcode.openfasttrace.core.Trace; import org.itsallcode.openfasttrace.mode.ReportMode; @@ -52,18 +52,18 @@ public TraceCommand(final CliArguments arguments) @Override public boolean run() { - final Reporter reporter = createReporter(); + final Report reporter = createReporter(); final Trace trace = report(reporter); return trace.hasNoDefects(); } - private Reporter createReporter() + private Report createReporter() { final ReportSettings settings = convertCommandLineArgumentsToReportSettings(); - final Reporter reporter = new ReportMode(); + final Report reporter = new ReportMode(); reporter.addInputs(toPaths(this.arguments.getInputs())) // .setFilters(createFilterSettingsFromArguments()) // - .configureReport(settings); + .configure(settings); return reporter; } @@ -71,11 +71,11 @@ private ReportSettings convertCommandLineArgumentsToReportSettings() { return new ReportSettings.Builder() .verbosity(this.arguments.getReportVerbosity()) - .newlineFormat(this.arguments.getNewline()) + .newline(this.arguments.getNewline()) .showOrigin(this.arguments.getShowOrigin()).build(); } - private Trace report(final Reporter reporter) + private Trace report(final Report reporter) { final Trace trace = reporter.trace(); final Path outputPath = this.arguments.getOutputPath(); @@ -85,7 +85,7 @@ private Trace report(final Reporter reporter) } else { - reporter.reportToFile(trace, this.arguments.getOutputPath()); + reporter.reportToPath(trace, this.arguments.getOutputPath()); } return trace; } diff --git a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java new file mode 100644 index 00000000..83c0572f --- /dev/null +++ b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java @@ -0,0 +1,111 @@ +package org.itsallcode.openfasttrace.core; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.itsallcode.openfasttrace.*; +import org.itsallcode.openfasttrace.core.serviceloader.InitializingServiceLoader; +import org.itsallcode.openfasttrace.importer.*; +import org.itsallcode.openfasttrace.report.ReportService; + +public class OftRunner implements Oft +{ + private final List inputs = new ArrayList<>(); + + @Override + public Oft addInputs(final Path... inputs) + { + for (final Path input : inputs) + { + this.inputs.add(input); + } + return this; + } + + @Override + public Oft addInputs(final List inputs) + { + this.inputs.addAll(inputs); + return this; + } + + @Override + public List importItems() + { + return createImporterService() // + .createImporter() // + .importAny(this.inputs) // + .getImportedItems(); + } + + private ImporterService createImporterService() + { + final ImportSettings settings = ImportSettings.createDefault(); + final ImporterContext context = new ImporterContext(settings); + final InitializingServiceLoader serviceLoader = InitializingServiceLoader + .load(ImporterFactory.class, context); + final ImporterService service = new ImporterService( + new ImporterFactoryLoader(serviceLoader), settings); + context.setImporterService(service); + return service; + } + + @Override + public List importItems(final ImportSettings settings) + { + return createImporterService() // + .createImporter() // + .importAny(this.inputs) // + .getImportedItems(); + } + + @Override + public List link(final List items) + { + return new Linker(items).link(); + } + + @Override + public Trace trace(final List linkedItems) + { + return new Tracer().trace(linkedItems); + } + + @Override + public void export(final List items) + { + // TODO Auto-generated method stub + } + + @Override + public void export(final List items, final ExportSettings settings) + { + // TODO Auto-generated method stub + } + + @Override + public void report(final Trace trace) + { + new ReportService().reportTraceToStdOut(trace, ReportSettings.createDefault()); + } + + @Override + public void report(final Trace trace, final ReportSettings settings) + { + new ReportService().reportTraceToStdOut(trace, settings); + } + + @Override + public void reportToPath(final Trace trace, final Path outputPath) + { + new ReportService().reportTraceToPath(trace, outputPath, ReportSettings.createDefault()); + } + + @Override + public void reportToPath(final Trace trace, final Path outputPath, + final ReportSettings settings) + { + new ReportService().reportTraceToPath(trace, outputPath, settings); + } +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java index 11535afc..492e3d9f 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java @@ -23,7 +23,7 @@ */ import java.util.Objects; -import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; +import org.itsallcode.openfasttrace.ImportSettings; /** * Common context shared by all {@link ImporterFactory}s. This allows importers @@ -31,18 +31,18 @@ */ public class ImporterContext { - private final TagImporterConfig tagImporterConfig; + private final ImportSettings settings; private ImporterService importerService; /** * Creates a new {@link ImporterContext}. * - * @param tagImporterConfig + * @param settings * importer specific configuration. */ - public ImporterContext(final TagImporterConfig tagImporterConfig) + public ImporterContext(final ImportSettings settings) { - this.tagImporterConfig = tagImporterConfig; + this.settings = settings; } /** @@ -72,8 +72,8 @@ public ImporterService getImporterService() * * @return importer specific configuration. */ - public TagImporterConfig getTagImporterConfig() + public ImportSettings getImportSettings() { - return this.tagImporterConfig; + return this.settings; } -} +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterService.java b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterService.java index dc351797..10927535 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterService.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterService.java @@ -23,7 +23,7 @@ */ import java.util.List; -import org.itsallcode.openfasttrace.FilterSettings; +import org.itsallcode.openfasttrace.ImportSettings; import org.itsallcode.openfasttrace.core.SpecificationItem; import org.itsallcode.openfasttrace.importer.input.InputFile; @@ -35,26 +35,29 @@ public class ImporterService { private final ImporterFactoryLoader factoryLoader; - private FilterSettings filterSettings; + private final ImportSettings settings; - public ImporterService(final ImporterFactoryLoader factoryLoader) + /** + * Create a new instance of an {@link ImporterService} + * + * @param factoryLoader + * loader for importer factories depending on the source + * @param settings + * import settings (e.g. filters) + */ + public ImporterService(final ImporterFactoryLoader factoryLoader, final ImportSettings settings) { this.factoryLoader = factoryLoader; + this.settings = settings; } /** - * Set the filters to be applied + * Import a file's contents * - * @param filterSettings - * filter settings - * @return this for fluent programming style + * @param file + * file to be imported + * @return list of recognized specification items */ - public ImporterService setFilters(final FilterSettings filterSettings) - { - this.filterSettings = filterSettings; - return this; - } - public List importFile(final InputFile file) { return createImporter() // @@ -69,6 +72,7 @@ public MultiFileImporter createImporter(final ImportEventListener builder) public MultiFileImporter createImporter() { - return createImporter(SpecificationListBuilder.createWithFilter(this.filterSettings)); + return createImporter( + SpecificationListBuilder.createWithFilter(this.settings.getFilters())); } -} +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java index c053aafb..e008f2ed 100644 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java +++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java @@ -7,6 +7,7 @@ import java.util.regex.Pattern; import java.util.stream.Stream; +import org.itsallcode.openfasttrace.ImportSettings; /*- * #%L * OpenFastTrace @@ -31,7 +32,6 @@ import org.itsallcode.openfasttrace.importer.*; import org.itsallcode.openfasttrace.importer.input.InputFile; import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; -import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; /** * {@link ImporterFactory} for tags in source code files. @@ -85,7 +85,7 @@ public Importer createImporter(final InputFile path, final ImportEventListener l private Stream getPathConfigs() { - final TagImporterConfig config = getContext().getTagImporterConfig(); - return config == null ? Stream.empty() : config.getPathConfigs().stream(); + final ImportSettings settings = getContext().getImportSettings(); + return settings == null ? Stream.empty() : settings.getPathConfigs().stream(); } } diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java deleted file mode 100644 index 7d1a4ff8..00000000 --- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.itsallcode.openfasttrace.importer.tag.config; - -/*- - * #%L - * OpenFastTrace - * %% - * Copyright (C) 2016 - 2018 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import static java.util.Collections.emptyList; - -import java.util.List; - -/** - * Configuration for the {@link ShortTagImportingLineConsumer}. - */ -public class TagImporterConfig -{ - private final List pathConfigs; - - /** - * Create a new configuration object. - * - * @param pathConfigs - * a list of {@link PathConfig} objects. - */ - public TagImporterConfig(final List pathConfigs) - { - this.pathConfigs = pathConfigs; - } - - /** - * Creates a new, empty configuration. - */ - public static TagImporterConfig empty() - { - return new TagImporterConfig(emptyList()); - } - - public List getPathConfigs() - { - return this.pathConfigs; - } -} diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java index ca73705a..57fdbea5 100644 --- a/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java +++ b/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java @@ -33,14 +33,14 @@ import org.itsallcode.openfasttrace.core.*; import org.itsallcode.openfasttrace.core.serviceloader.InitializingServiceLoader; import org.itsallcode.openfasttrace.importer.*; -import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImportSettings; abstract class AbstractMode> { protected final List inputs = new ArrayList<>(); protected Newline newline = Newline.UNIX; private FilterSettings filterSettings = FilterSettings.createAllowingEverything(); - private TagImporterConfig tagImporterConfig = TagImporterConfig.empty(); + private TagImportSettings tagImporterConfig = TagImportSettings.empty(); protected abstract T self(); @@ -68,7 +68,7 @@ public T setFilters(final FilterSettings filterSettings) return self(); } - public T setLegacyTagImporterPathConfig(final TagImporterConfig tagImporterConfig) + public T setLegacyTagImporterPathConfig(final TagImportSettings tagImporterConfig) { this.tagImporterConfig = tagImporterConfig; return self(); diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java index 01088a7e..ee151719 100644 --- a/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java +++ b/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java @@ -24,15 +24,15 @@ import java.nio.file.Path; -import org.itsallcode.openfasttrace.Converter; +import org.itsallcode.openfasttrace.Export; import org.itsallcode.openfasttrace.exporter.ExporterService; -public class ConvertMode extends AbstractMode implements Converter +public class ConvertMode extends AbstractMode implements Export { private final ExporterService exporterService = new ExporterService(); @Override - public void convertToFileInFormat(final Path output, final String format) + public void exportToFileInFormat(final Path output, final String format) { this.exporterService.exportFile(importItems(), format, output, this.newline); } diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java index 6c3221f7..3fc74702 100644 --- a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java +++ b/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java @@ -26,13 +26,13 @@ import java.util.List; import org.itsallcode.openfasttrace.ReportSettings; -import org.itsallcode.openfasttrace.Reporter; +import org.itsallcode.openfasttrace.Report; import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; import org.itsallcode.openfasttrace.core.Trace; import org.itsallcode.openfasttrace.core.Tracer; import org.itsallcode.openfasttrace.report.ReportService; -public class ReportMode extends AbstractMode implements Reporter +public class ReportMode extends AbstractMode implements Report { private final Tracer tracer = new Tracer(); private final ReportService reportService = new ReportService(); @@ -57,7 +57,7 @@ public ReportMode(final ReportSettings settings) } @Override - public Reporter configureReport(final ReportSettings settings) + public Report configure(final ReportSettings settings) { this.settings = settings; return this; diff --git a/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java b/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java index ca888558..77d76bdd 100644 --- a/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java +++ b/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java @@ -106,7 +106,7 @@ private void renderToPrintStream(final PrintStream report) break; case ALL: renderAll(report, this.settings.showOrigin()); - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); renderSummary(report); break; default: @@ -119,14 +119,14 @@ private void separateItemsFromSummary(final PrintStream report) { if (this.trace.countDefects() > 0) { - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); } } private void renderResultStatus(final PrintStream report) { report.print(translateStatus(this.trace.hasNoDefects())); - report.print(this.settings.getNewlineFormat().toString()); + report.print(this.settings.getNewline().toString()); } private String translateStatus(final boolean ok) @@ -147,7 +147,7 @@ private void renderSummary(final PrintStream report) report.print(this.trace.countDefects()); report.print(" defect"); } - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); } private void renderFailureIds(final PrintStream report) @@ -156,7 +156,7 @@ private void renderFailureIds(final PrintStream report) .sorted()// .forEachOrdered(id -> { report.print(id); - report.print(this.settings.getNewlineFormat().toString()); + report.print(this.settings.getNewline().toString()); }); } @@ -178,7 +178,7 @@ private void renderItemSummary(final PrintStream report, final LinkedSpecificati report.print(" "); renderMaturity(report, item); report.print(translateArtifactTypeCoverage(item)); - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); } private String translateArtifactTypeCoverage(final LinkedSpecificationItem item) @@ -263,7 +263,7 @@ private void renderOrigin(final PrintStream report, final Location location) private void renderEmptyItemDetailsLine(final PrintStream report) { report.print("|"); - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); } private void renderDescription(final PrintStream report, final LinkedSpecificationItem item) @@ -276,7 +276,7 @@ private void renderDescription(final PrintStream report, final LinkedSpecificati { report.print("| "); report.print(line); - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); } ++this.nonEmptySections; } @@ -312,7 +312,7 @@ private void renderLink(final PrintStream report, final TracedLink link, report.print(status.getShortTag()); report.print(") "); report.print(link.getOtherLinkEnd().getId()); - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); if (showOrigin) { final Location location = link.getOtherLinkEnd().getLocation(); @@ -320,7 +320,7 @@ private void renderLink(final PrintStream report, final TracedLink link, { report.print("| "); renderOrigin(report, location); - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); } } } @@ -333,7 +333,7 @@ private void renderTags(final PrintStream report, final LinkedSpecificationItem renderEmptyItemDetailsLine(report); report.print("| #: "); report.print(tags.stream().collect(Collectors.joining(", "))); - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); ++this.nonEmptySections; } } @@ -349,7 +349,7 @@ private void renderOrigin(final PrintStream report, final LinkedSpecificationIte report.print(":"); report.print(location.getLine()); report.print(")"); - report.print(this.settings.getNewlineFormat()); + report.print(this.settings.getNewline()); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java new file mode 100644 index 00000000..d7e206d2 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java @@ -0,0 +1,72 @@ +package org.itsallcode.openfasttrace; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +import org.itsallcode.openfasttrace.core.Newline; +import org.itsallcode.openfasttrace.exporter.ExporterConstants; +import org.junit.Before; +import org.junit.Test; + +/** + * This class implements a parameter object to control the settings of OFT's + * export mode. + */ +public class TestExportSettings +{ + private ExportSettings.Builder builder; + + @Before + public void before() + { + this.builder = new ExportSettings.Builder(); + } + + @Test + public void testDefaultOutputFormat() + { + assertThat(this.builder.build().getOutputFormat(), + equalTo(ExporterConstants.DEFAULT_OUTPUT_FORMAT)); + } + + @Test + public void testDefaultNewline() + { + assertThat(this.builder.build().getNewline(), equalTo(Newline.UNIX)); + } + + @Test + public void testBuildWithOutputFormat() + { + assertThat(this.builder.outputFormat("foo").build().getOutputFormat(), equalTo("foo")); + } + + @Test + public void testBuildWithNewline() + { + assertThat(this.builder.newline(Newline.OLDMAC).build().getNewline(), + equalTo(Newline.OLDMAC)); + } +} diff --git a/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java new file mode 100644 index 00000000..24168467 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java @@ -0,0 +1,77 @@ +package org.itsallcode.openfasttrace; + +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.collection.IsEmptyIterable.emptyIterableOf; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.junit.Assert.assertThat; + +import java.util.*; + +import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; +import org.junit.Test; + +/** + * This class implements a parameter object to control the settings of OFT's + * export mode. + */ +public class TestImportSettings +{ + @Test + public void testDefaultFilter() + { + assertThat(ImportSettings.createDefault().getFilters(), + equalTo(FilterSettings.createAllowingEverything())); + } + + @Test + public void testDefaultPathConfigs() + { + assertThat(ImportSettings.createDefault().getPathConfigs(), + emptyIterableOf(PathConfig.class)); + } + + @Test + public void testBuildWithFilter() + { + final String[] expectedTags = { "a", "b" }; + final FilterSettings filter = new FilterSettings.Builder() + .tags(new HashSet<>(Arrays.asList(expectedTags))).build(); + assertThat(new ImportSettings.Builder().filter(filter).build().getFilters().getTags(), + containsInAnyOrder(expectedTags)); + } + + @Test + public void testBuildWithPathConfigs() + { + final List expectedPathConfigs = new ArrayList<>(); + final PathConfig.Builder builder = PathConfig.builder(); + final PathConfig expectedFirstPathConfig = builder.patternPathMatcher("src") + .coveredItemArtifactType("a1").coveredItemNamePrefix("b1").tagArtifactType("c1") + .build(); + expectedPathConfigs.add(expectedFirstPathConfig); + assertThat(new ImportSettings.Builder().pathConfigs(expectedPathConfigs).build() + .getPathConfigs().get(0), equalTo(expectedFirstPathConfig)); + } +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java index 2ae1b049..26516d63 100644 --- a/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java +++ b/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java @@ -61,9 +61,9 @@ public void testDefaultOutputFormat() } @Test - public void testDefaultNewlineFormat() + public void testDefaultNewline() { - assertThat(this.builder.build().getNewlineFormat(), equalTo(Newline.UNIX)); + assertThat(this.builder.build().getNewline(), equalTo(Newline.UNIX)); } @Test @@ -86,9 +86,9 @@ public void testBuildWithOutputFormat() } @Test - public void testBuildWithNewlineFormat() + public void testBuildWithNewline() { - assertThat(this.builder.newlineFormat(Newline.OLDMAC).build().getNewlineFormat(), + assertThat(this.builder.newline(Newline.OLDMAC).build().getNewline(), equalTo(Newline.OLDMAC)); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java b/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java index 901a3906..1c38c9f5 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java @@ -34,7 +34,7 @@ import java.util.List; import org.itsallcode.openfasttrace.importer.input.InputFile; -import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImportSettings; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -60,7 +60,7 @@ public void initMocks() { MockitoAnnotations.initMocks(this); when(this.contextMock.getTagImporterConfig()) - .thenReturn(new TagImporterConfig(emptyList())); + .thenReturn(new TagImportSettings(emptyList())); } @Test diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java index 5652513d..806fcc38 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java @@ -25,7 +25,7 @@ import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; -import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImportSettings; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -34,7 +34,7 @@ public class TestImporterContext { @Mock - private TagImporterConfig configMock; + private TagImportSettings configMock; @Mock private ImporterService importerServiceMock; diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java index 89eb1a72..7ea4301e 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java @@ -38,7 +38,7 @@ import org.itsallcode.openfasttrace.importer.*; import org.itsallcode.openfasttrace.importer.input.InputFile; import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; -import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig; +import org.itsallcode.openfasttrace.importer.tag.config.TagImportSettings; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -119,25 +119,25 @@ public void testFactoryThrowsExceptionForMissingFile() throws IOException importer.runImport(); } - private void assertSupportsFile(final TagImporterConfig config, final String path, + private void assertSupportsFile(final TagImportSettings config, final String path, final boolean expected) { final InputFile file = InputFile.forPath(Paths.get(path)); assertThat(create(config).supportsFile(file), equalTo(expected)); } - private Importer createImporter(final TagImporterConfig config, final Path path) + private Importer createImporter(final TagImportSettings config, final Path path) { final InputFile file = InputFile.forPath(path, StandardCharsets.UTF_8); return create(config).createImporter(file, this.listenerMock); } - private TagImporterConfig configure(final PathConfig... pathConfigs) + private TagImportSettings configure(final PathConfig... pathConfigs) { - return new TagImporterConfig(asList(pathConfigs)); + return new TagImportSettings(asList(pathConfigs)); } - private TagImporterFactory create(final TagImporterConfig config) + private TagImporterFactory create(final TagImportSettings config) { final TagImporterFactory factory = new TagImporterFactory(); factory.init(this.contextMock); diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java b/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java index f76bc014..b2d698aa 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java @@ -22,15 +22,11 @@ * #L% */ - import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -85,4 +81,4 @@ protected void assertStdOutEmpty() { assertThat("STDOUT stream is empty", this.outputStream.size(), equalTo(0)); } -} +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java index 3a7b2b1a..6dcd491d 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java @@ -25,7 +25,7 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; -import org.itsallcode.openfasttrace.Converter; +import org.itsallcode.openfasttrace.Export; import org.itsallcode.openfasttrace.exporter.ExporterConstants; import org.junit.Before; import org.junit.Test; @@ -34,7 +34,7 @@ public class ITestConverter extends AbstractOftModeTest { private static final String REQM2_PREAMBLE = ""; - private Converter converter; + private Export converter; @Before public void setUp() throws UnsupportedEncodingException @@ -47,7 +47,7 @@ public void setUp() throws UnsupportedEncodingException public void testConvertToSpecobjectFile() throws IOException { this.converter.addInputs(this.docDir); - this.converter.convertToFileInFormat(this.outputFile, + this.converter.exportToFileInFormat(this.outputFile, ExporterConstants.DEFAULT_OUTPUT_FORMAT); assertStandardFileExportResult(); } diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java similarity index 63% rename from src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java rename to src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java index e5899a34..6527cee3 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java @@ -29,44 +29,40 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.file.Files; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; +import java.util.*; -import org.itsallcode.openfasttrace.FilterSettings; -import org.itsallcode.openfasttrace.ReportSettings; -import org.itsallcode.openfasttrace.Reporter; -import org.itsallcode.openfasttrace.core.Newline; -import org.itsallcode.openfasttrace.core.Trace; +import org.itsallcode.openfasttrace.*; +import org.itsallcode.openfasttrace.core.*; import org.itsallcode.openfasttrace.report.ReportVerbosity; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.SystemErrRule; -public class ITestReporter extends AbstractOftModeTest +public class ITestOftAsReporter extends AbstractOftModeTest { - private Reporter reporter; + private Oft oft; + @Rule + public final SystemErrRule systemErrRule = new SystemErrRule().enableLog(); + private Trace trace; + private List linkedItems; @Before public void setUp() throws UnsupportedEncodingException { perpareOutput(); - this.reporter = new ReportMode(); + this.oft = Oft.create().addInputs(this.docDir); + final List items = this.oft.importItems(); + this.linkedItems = this.oft.link(items); + this.trace = this.oft.trace(this.linkedItems); } @Test public void testTraceToFile() throws IOException { - final Trace trace = this.reporter.addInputs(this.docDir) // - .trace(); - writePlainTextReportFromTrace(trace); assertStandardReportFileResult(); } - private void writePlainTextReportFromTrace(final Trace trace) - { - this.reporter.reportToFile(trace, this.outputFile); - } - private void assertStandardReportFileResult() throws IOException { assertOutputFileExists(true); @@ -78,10 +74,7 @@ public void testTraceWithReportVerbosityMinimal() throws IOException { final ReportSettings settings = new ReportSettings.Builder() .verbosity(ReportVerbosity.MINIMAL).build(); - final Trace trace = this.reporter.addInputs(this.docDir) // - .configureReport(settings) // - .trace(); - writePlainTextReportFromTrace(trace); + this.oft.reportToPath(this.trace, this.outputFile, settings); assertOutputFileExists(true); assertOutputFileContentStartsWith("ok"); } @@ -90,12 +83,9 @@ public void testTraceWithReportVerbosityMinimal() throws IOException public void testTraceMacNewlines() throws IOException { final ReportSettings settings = new ReportSettings.Builder() // - .newlineFormat(Newline.OLDMAC) // + .newline(Newline.OLDMAC) // .build(); - final Trace trace = this.reporter.addInputs(this.docDir) // - .configureReport(settings) // - .trace(); - writePlainTextReportFromTrace(trace); + this.oft.reportToPath(this.trace, this.outputFile, settings); assertThat(Files.exists(this.outputFile), equalTo(true)); assertThat("Has old Mac newlines", getOutputFileContent().contains(CARRIAGE_RETURN), equalTo(true)); @@ -106,9 +96,9 @@ public void testTraceMacNewlines() throws IOException @Test public void testTraceToStdOut() throws IOException { - final Trace trace = this.reporter.addInputs(this.docDir) // - .trace(); - this.reporter.reportToStdOut(trace); + final List items = this.oft.addInputs(this.docDir).importItems(); + final Trace trace = this.oft.trace(this.oft.link(items)); + this.oft.report(trace); assertStandardReportStdOutResult(); } @@ -122,15 +112,24 @@ private void assertStandardReportStdOutResult() throws IOException public void testFilterAllowsAllAtrifactsButDsn() { final Set artifactTypes = new HashSet<>(Arrays.asList("feat", "req")); - this.reporter.addInputs(this.docDir); - final Trace fullTrace = this.reporter.trace(); assertThat("Number of items with type \"dsn\" in regular trace", - countItemsOfArtifactTypeInTrace("dsn", fullTrace), greaterThan(0L)); - final Trace trace = this.reporter // - .setFilters(new FilterSettings.Builder().artifactTypes(artifactTypes).build())// - .trace(); + countItemsOfArtifactTypeInTrace("dsn", this.trace), greaterThan(0L)); + final FilterSettings filterSettings = new FilterSettings.Builder() + .artifactTypes(artifactTypes).build(); + final Trace filteredTrace = traceWithFilters(filterSettings); assertThat("Number of items with ignored type \"dsn\" in filtered trace", - countItemsOfArtifactTypeInTrace("dsn", trace), equalTo(0L)); + countItemsOfArtifactTypeInTrace("dsn", filteredTrace), equalTo(0L)); + } + + private Trace traceWithFilters(final FilterSettings filterSettings) + { + final ImportSettings importSettings = new ImportSettings.Builder().filter(filterSettings) + .build(); + final List filteredItems = this.oft.importItems(importSettings); + final List filteredSpecificationItems = this.oft + .link(filteredItems); + final Trace filteredTrace = this.oft.trace(filteredSpecificationItems); + return filteredTrace; } private long countItemsOfArtifactTypeInTrace(final String artifactType, final Trace trace) diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java index 0c5ac6f5..6e9f989b 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java @@ -32,7 +32,7 @@ import java.util.stream.Collectors; import org.itsallcode.openfasttrace.FilterSettings; -import org.itsallcode.openfasttrace.Reporter; +import org.itsallcode.openfasttrace.Report; import org.itsallcode.openfasttrace.core.Trace; import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest; import org.junit.Before; @@ -61,7 +61,7 @@ public class ITestReporterWithFilter extends AbstractFileBasedTest @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); - private Reporter reporter; + private Report reporter; @Before public void before() throws IOException diff --git a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java index 97f162f3..2f2c74b9 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java @@ -118,7 +118,7 @@ private String getReportOutputWithNewline(final ReportVerbosity verbosity, { final OutputStream outputStream = new ByteArrayOutputStream(); final ReportSettings settings = new ReportSettings.Builder().verbosity(verbosity) - .newlineFormat(newline).showOrigin(showOrigin).build(); + .newline(newline).showOrigin(showOrigin).build(); final Reportable report = new PlainTextReport(this.traceMock, settings); report.renderToStream(outputStream); return outputStream.toString(); From 1e66c59bc6d8a815bf61fcbab7e7d99827778e18 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Tue, 9 Oct 2018 19:54:52 +0200 Subject: [PATCH 54/60] #165: Commit before removing modes. --- .settings/org.eclipse.jdt.core.prefs | 492 ------------------ .../cli/commands/AbstractCommand.java | 13 + .../cli/commands/ConvertCommand.java | 51 +- .../cli/commands/TraceCommand.java | 48 +- .../openfasttrace/core/OftRunner.java | 14 +- ...tOftModeTest.java => AbstractOftTest.java} | 2 +- .../openfasttrace/mode/ITestConverter.java | 2 +- .../mode/ITestOftAsReporter.java | 7 +- .../mode/ITestReporterWithFilter.java | 18 +- .../testutil/AbstractFileBasedTest.java | 2 +- 10 files changed, 74 insertions(+), 575 deletions(-) rename src/test/java/org/itsallcode/openfasttrace/mode/{AbstractOftModeTest.java => AbstractOftTest.java} (98%) diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index ce711731..f4d834da 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,502 +1,10 @@ eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullable.secondary= -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled - org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.APILeak=warning -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled -org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.processAnnotations=disabled -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.APILeak=warning -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled -org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.processAnnotations=disabled -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.APILeak=warning -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled -org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.processAnnotations=disabled -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.APILeak=warning -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled -org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.processAnnotations=disabled -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.APILeak=warning -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning -org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled -org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.processAnnotations=disabled org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java index e5fbb7e5..f6e02235 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java @@ -30,7 +30,10 @@ import java.util.Set; import org.itsallcode.openfasttrace.FilterSettings; +import org.itsallcode.openfasttrace.ImportSettings; +import org.itsallcode.openfasttrace.Oft; import org.itsallcode.openfasttrace.cli.CliArguments; +import org.itsallcode.openfasttrace.core.SpecificationItem; /** * This class is the abstract base class for all commands that process a list of @@ -39,10 +42,12 @@ public abstract class AbstractCommand implements Performable { protected CliArguments arguments; + protected final Oft oft; protected AbstractCommand(final CliArguments arguments) { this.arguments = arguments; + this.oft = Oft.create(); } public List toPaths(final List inputs) @@ -89,4 +94,12 @@ private void setTagFilter(final FilterSettings.Builder builder) builder.tags(wantedTags); } } + + protected List importItems() + { + this.oft.addInputs(this.toPaths(this.arguments.getInputs())); + final ImportSettings importSettings = new ImportSettings.Builder() + .filter(createFilterSettingsFromArguments()).build(); + return this.oft.importItems(importSettings); + } } \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java index 73bcb603..ddf3aa4c 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java @@ -1,33 +1,11 @@ package org.itsallcode.openfasttrace.cli.commands; -/*- - * #%L - \* OpenFastTrace - * %% - * Copyright (C) 2016 - 2017 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import java.nio.file.Path; +import java.util.List; -import org.itsallcode.openfasttrace.Export; +import org.itsallcode.openfasttrace.ExportSettings; import org.itsallcode.openfasttrace.cli.CliArguments; -import org.itsallcode.openfasttrace.mode.ConvertMode; +import org.itsallcode.openfasttrace.core.SpecificationItem; /** * Handler for specification item conversion CLI command. @@ -50,23 +28,22 @@ public ConvertCommand(final CliArguments arguments) @Override public boolean run() { - final Export converter = createConverter(); - convert(converter); + final List items = importItems(); + convert(items); return true; } - private Export createConverter() + private void convert(final List items) { - final Export converter = new ConvertMode(); - converter.addInputs(toPaths(this.arguments.getInputs())) // - .setFilters(createFilterSettingsFromArguments()) // - .setNewline(this.arguments.getNewline()); - return converter; + final ExportSettings exportSettings = createExportSettingsFromArguments(); + this.oft.export(items, exportSettings); } - private void convert(final Export converter) + private ExportSettings createExportSettingsFromArguments() { - final Path outputPath = this.arguments.getOutputPath(); - converter.exportToFileInFormat(outputPath, this.arguments.getOutputFormat()); + return new ExportSettings.Builder() // + .newline(this.arguments.getNewline()) // + .outputFormat(this.arguments.getOutputFormat()) // + .build(); } -} +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java index 9069feaf..290a7ba1 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java @@ -24,12 +24,14 @@ */ import java.nio.file.Path; +import java.util.List; +import org.itsallcode.openfasttrace.Oft; import org.itsallcode.openfasttrace.ReportSettings; -import org.itsallcode.openfasttrace.Report; import org.itsallcode.openfasttrace.cli.CliArguments; +import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; +import org.itsallcode.openfasttrace.core.SpecificationItem; import org.itsallcode.openfasttrace.core.Trace; -import org.itsallcode.openfasttrace.mode.ReportMode; /** * Handler for requirement tracing CLI command. @@ -52,41 +54,43 @@ public TraceCommand(final CliArguments arguments) @Override public boolean run() { - final Report reporter = createReporter(); - final Trace trace = report(reporter); + final List items = importItems(); + final List linkedItems = linkItems(items); + final Trace trace = traceItems(linkedItems); + report(this.oft, trace); return trace.hasNoDefects(); } - private Report createReporter() + private List linkItems(final List items) { - final ReportSettings settings = convertCommandLineArgumentsToReportSettings(); - final Report reporter = new ReportMode(); - reporter.addInputs(toPaths(this.arguments.getInputs())) // - .setFilters(createFilterSettingsFromArguments()) // - .configure(settings); - return reporter; + return this.oft.link(items); } - private ReportSettings convertCommandLineArgumentsToReportSettings() + private Trace traceItems(final List linkedItems) { - return new ReportSettings.Builder() - .verbosity(this.arguments.getReportVerbosity()) - .newline(this.arguments.getNewline()) - .showOrigin(this.arguments.getShowOrigin()).build(); + return this.oft.trace(linkedItems); } - private Trace report(final Report reporter) + private void report(final Oft oft, final Trace trace) { - final Trace trace = reporter.trace(); final Path outputPath = this.arguments.getOutputPath(); + final ReportSettings reportSettings = convertCommandLineArgumentsToReportSettings(); if (null == outputPath) { - reporter.reportToStdOut(trace); + oft.report(trace, reportSettings); } else { - reporter.reportToPath(trace, this.arguments.getOutputPath()); + oft.reportToPath(trace, this.arguments.getOutputPath(), reportSettings); } - return trace; } -} + + private ReportSettings convertCommandLineArgumentsToReportSettings() + { + return new ReportSettings.Builder() // + .verbosity(this.arguments.getReportVerbosity()) // + .newline(this.arguments.getNewline()) // + .showOrigin(this.arguments.getShowOrigin()) // + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java index 83c0572f..7fb2fecb 100644 --- a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java +++ b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java @@ -31,17 +31,16 @@ public Oft addInputs(final List inputs) } @Override - public List importItems() + public List importItems(final ImportSettings settings) { - return createImporterService() // + return createImporterService(settings) // .createImporter() // .importAny(this.inputs) // .getImportedItems(); } - private ImporterService createImporterService() + private ImporterService createImporterService(final ImportSettings settings) { - final ImportSettings settings = ImportSettings.createDefault(); final ImporterContext context = new ImporterContext(settings); final InitializingServiceLoader serviceLoader = InitializingServiceLoader .load(ImporterFactory.class, context); @@ -52,12 +51,9 @@ private ImporterService createImporterService() } @Override - public List importItems(final ImportSettings settings) + public List importItems() { - return createImporterService() // - .createImporter() // - .importAny(this.inputs) // - .getImportedItems(); + return importItems(ImportSettings.createDefault()); } @Override diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java b/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftTest.java similarity index 98% rename from src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java rename to src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftTest.java index b2d698aa..61efcb77 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftTest.java @@ -35,7 +35,7 @@ import org.junit.Rule; import org.junit.rules.TemporaryFolder; -public abstract class AbstractOftModeTest +public abstract class AbstractOftTest { protected static final String NEWLINE = "\n"; diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java index 6dcd491d..8f2b9982 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java @@ -30,7 +30,7 @@ import org.junit.Before; import org.junit.Test; -public class ITestConverter extends AbstractOftModeTest +public class ITestConverter extends AbstractOftTest { private static final String REQM2_PREAMBLE = ""; diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java index 6527cee3..05b39546 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java @@ -39,7 +39,7 @@ import org.junit.Test; import org.junit.contrib.java.lang.system.SystemErrRule; -public class ITestOftAsReporter extends AbstractOftModeTest +public class ITestOftAsReporter extends AbstractOftTest { private Oft oft; @Rule @@ -60,6 +60,7 @@ public void setUp() throws UnsupportedEncodingException @Test public void testTraceToFile() throws IOException { + this.oft.reportToPath(this.trace, this.outputFile); assertStandardReportFileResult(); } @@ -96,9 +97,7 @@ public void testTraceMacNewlines() throws IOException @Test public void testTraceToStdOut() throws IOException { - final List items = this.oft.addInputs(this.docDir).importItems(); - final Trace trace = this.oft.trace(this.oft.link(items)); - this.oft.report(trace); + this.oft.report(this.trace); assertStandardReportStdOutResult(); } diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java index 6e9f989b..194e9032 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java @@ -32,7 +32,10 @@ import java.util.stream.Collectors; import org.itsallcode.openfasttrace.FilterSettings; -import org.itsallcode.openfasttrace.Report; +import org.itsallcode.openfasttrace.ImportSettings; +import org.itsallcode.openfasttrace.Oft; +import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; +import org.itsallcode.openfasttrace.core.SpecificationItem; import org.itsallcode.openfasttrace.core.Trace; import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest; import org.junit.Before; @@ -61,14 +64,13 @@ public class ITestReporterWithFilter extends AbstractFileBasedTest @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); - private Report reporter; + private Oft oft; @Before public void before() throws IOException { writeTextFile(this.tempFolder.newFile("spec.md"), SPECIFICATION); - this.reporter = new ReportMode(); - this.reporter.addInputs(this.tempFolder.getRoot().toPath()); + this.oft = Oft.create().addInputs(this.tempFolder.getRoot().toPath()); } // [itest->dsn~filtering-by-tags-during-import~1] @@ -85,9 +87,10 @@ public void testFilterWithAtLeastOneMatchingTag() private List getIdsFromTraceWithFilterSettings(final FilterSettings filterSettings) { - final Trace trace = this.reporter // - .setFilters(filterSettings) // - .trace(); + final List items = this.oft + .importItems(new ImportSettings.Builder().filter(filterSettings).build()); + final List linkedItems = this.oft.link(items); + final Trace trace = this.oft.trace(linkedItems); final List filteredIds = trace.getItems() // .stream() // .map(item -> item.getId().toString()) // @@ -104,6 +107,5 @@ public void testFilterWithAtLeastOneMatchingTagOrNoTags() .build(); final List filteredIds = getIdsFromTraceWithFilterSettings(filterSettings); assertThat(filteredIds, containsInAnyOrder("feat~a~1", "req~b~2", "dsn~c~3", "impl~d~4")); - } } \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java index fba40cfc..7ff7a055 100644 --- a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java @@ -45,4 +45,4 @@ protected void runWithArguments(final String... args) { CliStarter.main(args); } -} +} \ No newline at end of file From a16113ca1db45f57b55cbdd6bc1d93e1ac27350e Mon Sep 17 00:00:00 2001 From: redcatbear Date: Tue, 9 Oct 2018 21:21:23 +0200 Subject: [PATCH 55/60] #165: Refactoring complete. All tests green. --- .../openfasttrace/ExportSettings.java | 24 +++- .../openfasttrace/ImportSettings.java | 14 ++- .../org/itsallcode/openfasttrace/Oft.java | 19 +++- .../cli/commands/AbstractCommand.java | 2 +- .../cli/commands/ConvertCommand.java | 4 +- .../cli/commands/TraceCommand.java | 2 +- .../openfasttrace/core/OftRunner.java | 14 ++- .../exporter/ExporterFactory.java | 2 +- .../exporter/ExporterService.java | 21 ++-- .../openfasttrace/mode/AbstractMode.java | 104 ------------------ .../openfasttrace/mode/ConvertMode.java | 45 -------- .../openfasttrace/mode/ReportMode.java | 90 --------------- .../openfasttrace/TestExportSettings.java | 2 +- .../openfasttrace/TestImportSettings.java | 4 +- .../importer/ImporterFactoryTestBase.java | 7 +- .../importer/TestImporterContext.java | 10 +- .../importer/TestImporterService.java | 4 +- .../tag/TestTagImporterFactoryWithConfig.java | 18 +-- ...onverter.java => ITestOftAsConverter.java} | 20 ++-- .../mode/ITestOftAsReporter.java | 4 +- .../mode/ITestReporterWithFilter.java | 2 +- 21 files changed, 107 insertions(+), 305 deletions(-) delete mode 100644 src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java delete mode 100644 src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java delete mode 100644 src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java rename src/test/java/org/itsallcode/openfasttrace/mode/{ITestConverter.java => ITestOftAsConverter.java} (78%) diff --git a/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java index 7482a406..bf71287d 100644 --- a/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java +++ b/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java @@ -60,6 +60,24 @@ public Newline getNewline() return this.newline; } + /** + * Create default exporter settings + * + * @return default exporter settings + */ + public static ExportSettings createDefault() + { + return builder().build(); + } + + /** + * Create an export settings builder + */ + public static Builder builder() + { + return new Builder(); + } + /** * Builder for {@link ExportSettings} */ @@ -68,6 +86,10 @@ public static class Builder private String outputFormat = ExporterConstants.DEFAULT_OUTPUT_FORMAT; private Newline newline = Newline.UNIX; + private Builder() + { + } + /** * Set the converter output format * @@ -104,4 +126,4 @@ public ExportSettings build() return new ExportSettings(this); } } -} +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java index a68c595c..0d7c7022 100644 --- a/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java +++ b/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java @@ -66,7 +66,15 @@ public List getPathConfigs() */ public static ImportSettings createDefault() { - return new Builder().build(); + return builder().build(); + } + + /** + * Create an export settings builder + */ + public static Builder builder() + { + return new Builder(); } /** @@ -77,6 +85,10 @@ public static class Builder private FilterSettings filter = FilterSettings.createAllowingEverything(); private List pathConfigs = new ArrayList<>(); + private Builder() + { + } + /** * Set the filters to be used during import * diff --git a/src/main/java/org/itsallcode/openfasttrace/Oft.java b/src/main/java/org/itsallcode/openfasttrace/Oft.java index 503070e6..8d249f31 100644 --- a/src/main/java/org/itsallcode/openfasttrace/Oft.java +++ b/src/main/java/org/itsallcode/openfasttrace/Oft.java @@ -1,4 +1,3 @@ - package org.itsallcode.openfasttrace; /*- @@ -88,21 +87,31 @@ public interface Oft /** * Export items with default settings + * + * @param items + * items to be exported + * @param path + * output path for export */ - public void export(List items); + public void exportToPath(List items, final Path path); /** * Export items * + * @param items + * items to be exported + * @param path + * output path for export * @param settings * export settings */ - public void export(List items, ExportSettings settings); + public void exportToPath(final List items, final Path path, + ExportSettings settings); /** * Generate a report with default settings */ - public void report(Trace trace); + public void reportToStdOut(Trace trace); /** * Generate a report @@ -113,7 +122,7 @@ public interface Oft * @param settings * report settings */ - public void report(Trace trace, ReportSettings settings); + public void reportToStdOut(Trace trace, ReportSettings settings); /** * Generate a report diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java index f6e02235..130397ec 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java @@ -98,7 +98,7 @@ private void setTagFilter(final FilterSettings.Builder builder) protected List importItems() { this.oft.addInputs(this.toPaths(this.arguments.getInputs())); - final ImportSettings importSettings = new ImportSettings.Builder() + final ImportSettings importSettings = ImportSettings.builder() .filter(createFilterSettingsFromArguments()).build(); return this.oft.importItems(importSettings); } diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java index ddf3aa4c..3fade694 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java @@ -36,12 +36,12 @@ public boolean run() private void convert(final List items) { final ExportSettings exportSettings = createExportSettingsFromArguments(); - this.oft.export(items, exportSettings); + this.oft.exportToPath(items, this.arguments.getOutputPath(), exportSettings); } private ExportSettings createExportSettingsFromArguments() { - return new ExportSettings.Builder() // + return ExportSettings.builder() // .newline(this.arguments.getNewline()) // .outputFormat(this.arguments.getOutputFormat()) // .build(); diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java index 290a7ba1..e56123b1 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java @@ -77,7 +77,7 @@ private void report(final Oft oft, final Trace trace) final ReportSettings reportSettings = convertCommandLineArgumentsToReportSettings(); if (null == outputPath) { - oft.report(trace, reportSettings); + oft.reportToStdOut(trace, reportSettings); } else { diff --git a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java index 7fb2fecb..a2bf7c58 100644 --- a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java +++ b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java @@ -6,6 +6,7 @@ import org.itsallcode.openfasttrace.*; import org.itsallcode.openfasttrace.core.serviceloader.InitializingServiceLoader; +import org.itsallcode.openfasttrace.exporter.ExporterService; import org.itsallcode.openfasttrace.importer.*; import org.itsallcode.openfasttrace.report.ReportService; @@ -69,25 +70,26 @@ public Trace trace(final List linkedItems) } @Override - public void export(final List items) + public void exportToPath(final List items, final Path path) { - // TODO Auto-generated method stub + exportToPath(items, path, ExportSettings.createDefault()); } @Override - public void export(final List items, final ExportSettings settings) + public void exportToPath(final List items, final Path path, + final ExportSettings settings) { - // TODO Auto-generated method stub + new ExporterService().exportToPath(items.stream(), path, settings); } @Override - public void report(final Trace trace) + public void reportToStdOut(final Trace trace) { new ReportService().reportTraceToStdOut(trace, ReportSettings.createDefault()); } @Override - public void report(final Trace trace, final ReportSettings settings) + public void reportToStdOut(final Trace trace, final ReportSettings settings) { new ReportService().reportTraceToStdOut(trace, settings); } diff --git a/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterFactory.java b/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterFactory.java index dff87ae6..0d2a6bc7 100644 --- a/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterFactory.java +++ b/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterFactory.java @@ -147,4 +147,4 @@ private Writer createFileWriter(final Path file, final Charset charset) */ protected abstract Exporter createExporter(final Writer writer, Stream linkedSpecItemStream, final Newline newline); -} +} \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterService.java b/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterService.java index 90bf5abb..37df83be 100644 --- a/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterService.java +++ b/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterService.java @@ -26,8 +26,8 @@ import java.nio.file.Path; import java.util.stream.Stream; +import org.itsallcode.openfasttrace.ExportSettings; import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; -import org.itsallcode.openfasttrace.core.Newline; import org.itsallcode.openfasttrace.core.SpecificationItem; public class ExporterService @@ -51,18 +51,15 @@ public ExporterService(final ExporterFactoryLoader factoryLoader) * * @param itemStream * the {@link SpecificationItem} to export - * @param format - * the output format - * @param outputFile - * the output file - * @param newline - * the newline format + * @param settings + * the exporter settings */ - public void exportFile(final Stream itemStream, final String format, - final Path outputFile, final Newline newline) + public void exportToPath(final Stream itemStream, final Path outputFile, + final ExportSettings settings) { - final ExporterFactory factory = this.factoryLoader.getExporterFactory(format); - factory.createExporter(outputFile, format, StandardCharsets.UTF_8, newline, itemStream) - .runExport(); + final ExporterFactory factory = this.factoryLoader + .getExporterFactory(settings.getOutputFormat()); + factory.createExporter(outputFile, settings.getOutputFormat(), StandardCharsets.UTF_8, + settings.getNewline(), itemStream).runExport(); } } diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java deleted file mode 100644 index 57fdbea5..00000000 --- a/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.itsallcode.openfasttrace.mode; - -/*- - * #%L - \* OpenFastTrace - * %% - * Copyright (C) 2016 - 2017 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.itsallcode.openfasttrace.FilterSettings; -import org.itsallcode.openfasttrace.core.*; -import org.itsallcode.openfasttrace.core.serviceloader.InitializingServiceLoader; -import org.itsallcode.openfasttrace.importer.*; -import org.itsallcode.openfasttrace.importer.tag.config.TagImportSettings; - -abstract class AbstractMode> -{ - protected final List inputs = new ArrayList<>(); - protected Newline newline = Newline.UNIX; - private FilterSettings filterSettings = FilterSettings.createAllowingEverything(); - private TagImportSettings tagImporterConfig = TagImportSettings.empty(); - - protected abstract T self(); - - public T addInputs(final Path... inputs) - { - return this.addInputs(Arrays.asList(inputs)); - } - - public T addInputs(final List inputs) - { - this.inputs.addAll(inputs); - return self(); - } - - public T setNewline(final Newline newline) - { - - this.newline = newline; - return self(); - } - - public T setFilters(final FilterSettings filterSettings) - { - this.filterSettings = filterSettings; - return self(); - } - - public T setLegacyTagImporterPathConfig(final TagImportSettings tagImporterConfig) - { - this.tagImporterConfig = tagImporterConfig; - return self(); - } - - protected List importLinkedSpecificationItems() - { - final Stream items = importItems(); - final Linker linker = new Linker(items.collect(Collectors.toList())); - return linker.link(); - } - - protected Stream importItems() - { - return createImporterService() // - .setFilters(this.filterSettings) // - .createImporter() // - .importAny(this.inputs) // - .getImportedItems() // - .stream(); - } - - private ImporterService createImporterService() - { - final ImporterContext context = new ImporterContext(this.tagImporterConfig); - final InitializingServiceLoader serviceLoader = InitializingServiceLoader - .load(ImporterFactory.class, context); - final ImporterService service = new ImporterService( - new ImporterFactoryLoader(serviceLoader)); - context.setImporterService(service); - return service; - } -} diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java deleted file mode 100644 index ee151719..00000000 --- a/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.itsallcode.openfasttrace.mode; - -/*- - * #%L - \* OpenFastTrace - * %% - * Copyright (C) 2016 - 2017 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import java.nio.file.Path; - -import org.itsallcode.openfasttrace.Export; -import org.itsallcode.openfasttrace.exporter.ExporterService; - -public class ConvertMode extends AbstractMode implements Export -{ - private final ExporterService exporterService = new ExporterService(); - - @Override - public void exportToFileInFormat(final Path output, final String format) - { - this.exporterService.exportFile(importItems(), format, output, this.newline); - } - - @Override - protected ConvertMode self() - { - return this; - } -} diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java deleted file mode 100644 index 3fc74702..00000000 --- a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.itsallcode.openfasttrace.mode; - -/*- - * #%L - \* OpenFastTrace - * %% - * Copyright (C) 2016 - 2017 itsallcode.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import java.nio.file.Path; -import java.util.List; - -import org.itsallcode.openfasttrace.ReportSettings; -import org.itsallcode.openfasttrace.Report; -import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; -import org.itsallcode.openfasttrace.core.Trace; -import org.itsallcode.openfasttrace.core.Tracer; -import org.itsallcode.openfasttrace.report.ReportService; - -public class ReportMode extends AbstractMode implements Report -{ - private final Tracer tracer = new Tracer(); - private final ReportService reportService = new ReportService(); - private ReportSettings settings; - - /** - * Create a new instance of a {@link ReportMode} using the default report - * settings. - */ - public ReportMode() - { - this(new ReportSettings.Builder().build()); - } - - /** - * Create a new instance of a {@link ReportMode} using the custom report - * settings. - */ - public ReportMode(final ReportSettings settings) - { - this.settings = settings; - } - - @Override - public Report configure(final ReportSettings settings) - { - this.settings = settings; - return this; - } - - @Override - public Trace trace() - { - final List linkedItems = importLinkedSpecificationItems(); - return this.tracer.trace(linkedItems); - } - - @Override - public void reportToFile(final Trace trace, final Path output) - { - this.reportService.reportTraceToPath(trace, output, this.settings); - } - - @Override - public void reportToStdOut(final Trace trace) - { - this.reportService.reportTraceToStdOut(trace, this.settings); - } - - @Override - protected ReportMode self() - { - return this; - } -} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java index d7e206d2..b01575a1 100644 --- a/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java +++ b/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java @@ -41,7 +41,7 @@ public class TestExportSettings @Before public void before() { - this.builder = new ExportSettings.Builder(); + this.builder = ExportSettings.builder(); } @Test diff --git a/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java index 24168467..e14ca7fc 100644 --- a/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java +++ b/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java @@ -58,7 +58,7 @@ public void testBuildWithFilter() final String[] expectedTags = { "a", "b" }; final FilterSettings filter = new FilterSettings.Builder() .tags(new HashSet<>(Arrays.asList(expectedTags))).build(); - assertThat(new ImportSettings.Builder().filter(filter).build().getFilters().getTags(), + assertThat(ImportSettings.builder().filter(filter).build().getFilters().getTags(), containsInAnyOrder(expectedTags)); } @@ -71,7 +71,7 @@ public void testBuildWithPathConfigs() .coveredItemArtifactType("a1").coveredItemNamePrefix("b1").tagArtifactType("c1") .build(); expectedPathConfigs.add(expectedFirstPathConfig); - assertThat(new ImportSettings.Builder().pathConfigs(expectedPathConfigs).build() + assertThat(ImportSettings.builder().pathConfigs(expectedPathConfigs).build() .getPathConfigs().get(0), equalTo(expectedFirstPathConfig)); } } \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java b/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java index 1c38c9f5..fcac4f28 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java @@ -1,7 +1,5 @@ package org.itsallcode.openfasttrace.importer; -import static java.util.Collections.emptyList; - /*- * #%L \* OpenFastTrace @@ -33,8 +31,8 @@ import java.nio.file.Paths; import java.util.List; +import org.itsallcode.openfasttrace.ImportSettings; import org.itsallcode.openfasttrace.importer.input.InputFile; -import org.itsallcode.openfasttrace.importer.tag.config.TagImportSettings; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -59,8 +57,7 @@ public abstract class ImporterFactoryTestBase public void initMocks() { MockitoAnnotations.initMocks(this); - when(this.contextMock.getTagImporterConfig()) - .thenReturn(new TagImportSettings(emptyList())); + when(this.contextMock.getImportSettings()).thenReturn(ImportSettings.createDefault()); } @Test diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java index 806fcc38..239984a5 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java @@ -25,7 +25,7 @@ import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; -import org.itsallcode.openfasttrace.importer.tag.config.TagImportSettings; +import org.itsallcode.openfasttrace.ImportSettings; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -34,7 +34,7 @@ public class TestImporterContext { @Mock - private TagImportSettings configMock; + private ImportSettings settingsMock; @Mock private ImporterService importerServiceMock; @@ -44,13 +44,13 @@ public class TestImporterContext public void setup() { MockitoAnnotations.initMocks(this); - this.context = new ImporterContext(this.configMock); + this.context = new ImporterContext(this.settingsMock); } @Test public void testGetImporterConfig() { - assertThat(this.context.getTagImporterConfig(), sameInstance(this.configMock)); + assertThat(this.context.getImportSettings(), sameInstance(this.settingsMock)); } @Test(expected = NullPointerException.class) @@ -65,4 +65,4 @@ public void testGetImporterService() this.context.setImporterService(this.importerServiceMock); assertThat(this.context.getImporterService(), sameInstance(this.importerServiceMock)); } -} +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterService.java b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterService.java index f3723136..99de953b 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterService.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterService.java @@ -33,6 +33,7 @@ import java.nio.file.Paths; import java.util.List; +import org.itsallcode.openfasttrace.ImportSettings; import org.itsallcode.openfasttrace.core.SpecificationItem; import org.itsallcode.openfasttrace.importer.input.InputFile; import org.itsallcode.openfasttrace.testutil.OsDetector; @@ -67,7 +68,8 @@ public class TestImporterService public void setUp() { MockitoAnnotations.initMocks(this); - this.importerService = new ImporterService(this.factoryLoaderMock); + this.importerService = new ImporterService(this.factoryLoaderMock, + ImportSettings.createDefault()); this.file = InputFile.forPath(Paths.get("dir", "file")); when(this.factoryLoaderMock.getImporterFactory(any(InputFile.class))) diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java index 7ea4301e..6ad36dac 100644 --- a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java +++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java @@ -35,10 +35,10 @@ import java.nio.file.Path; import java.nio.file.Paths; +import org.itsallcode.openfasttrace.ImportSettings; import org.itsallcode.openfasttrace.importer.*; import org.itsallcode.openfasttrace.importer.input.InputFile; import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; -import org.itsallcode.openfasttrace.importer.tag.config.TagImportSettings; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -119,29 +119,29 @@ public void testFactoryThrowsExceptionForMissingFile() throws IOException importer.runImport(); } - private void assertSupportsFile(final TagImportSettings config, final String path, + private void assertSupportsFile(final ImportSettings settings, final String path, final boolean expected) { final InputFile file = InputFile.forPath(Paths.get(path)); - assertThat(create(config).supportsFile(file), equalTo(expected)); + assertThat(create(settings).supportsFile(file), equalTo(expected)); } - private Importer createImporter(final TagImportSettings config, final Path path) + private Importer createImporter(final ImportSettings settings, final Path path) { final InputFile file = InputFile.forPath(path, StandardCharsets.UTF_8); - return create(config).createImporter(file, this.listenerMock); + return create(settings).createImporter(file, this.listenerMock); } - private TagImportSettings configure(final PathConfig... pathConfigs) + private ImportSettings configure(final PathConfig... pathConfigs) { - return new TagImportSettings(asList(pathConfigs)); + return ImportSettings.builder().pathConfigs(asList(pathConfigs)).build(); } - private TagImporterFactory create(final TagImportSettings config) + private TagImporterFactory create(final ImportSettings settings) { final TagImporterFactory factory = new TagImporterFactory(); factory.init(this.contextMock); - when(this.contextMock.getTagImporterConfig()).thenReturn(config); + when(this.contextMock.getImportSettings()).thenReturn(settings); return factory; } diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java similarity index 78% rename from src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java rename to src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java index 8f2b9982..a2274bb4 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java @@ -24,31 +24,31 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.List; -import org.itsallcode.openfasttrace.Export; -import org.itsallcode.openfasttrace.exporter.ExporterConstants; +import org.itsallcode.openfasttrace.Oft; +import org.itsallcode.openfasttrace.core.SpecificationItem; import org.junit.Before; import org.junit.Test; -public class ITestConverter extends AbstractOftTest +public class ITestOftAsConverter extends AbstractOftTest { private static final String REQM2_PREAMBLE = ""; - - private Export converter; + private Oft oft; @Before public void setUp() throws UnsupportedEncodingException { perpareOutput(); - this.converter = new ConvertMode(); + this.oft = Oft.create(); } @Test public void testConvertToSpecobjectFile() throws IOException { - this.converter.addInputs(this.docDir); - this.converter.exportToFileInFormat(this.outputFile, - ExporterConstants.DEFAULT_OUTPUT_FORMAT); + this.oft.addInputs(this.docDir); + final List items = this.oft.importItems(); + this.oft.exportToPath(items, this.outputFile); assertStandardFileExportResult(); } @@ -57,4 +57,4 @@ private void assertStandardFileExportResult() throws IOException assertOutputFileExists(true); assertOutputFileContentStartsWith(REQM2_PREAMBLE + ""); } -} +} \ No newline at end of file diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java index 05b39546..2b5b5bf6 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java @@ -97,7 +97,7 @@ public void testTraceMacNewlines() throws IOException @Test public void testTraceToStdOut() throws IOException { - this.oft.report(this.trace); + this.oft.reportToStdOut(this.trace); assertStandardReportStdOutResult(); } @@ -122,7 +122,7 @@ public void testFilterAllowsAllAtrifactsButDsn() private Trace traceWithFilters(final FilterSettings filterSettings) { - final ImportSettings importSettings = new ImportSettings.Builder().filter(filterSettings) + final ImportSettings importSettings = ImportSettings.builder().filter(filterSettings) .build(); final List filteredItems = this.oft.importItems(importSettings); final List filteredSpecificationItems = this.oft diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java index 194e9032..e5abbb86 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java @@ -88,7 +88,7 @@ public void testFilterWithAtLeastOneMatchingTag() private List getIdsFromTraceWithFilterSettings(final FilterSettings filterSettings) { final List items = this.oft - .importItems(new ImportSettings.Builder().filter(filterSettings).build()); + .importItems(ImportSettings.builder().filter(filterSettings).build()); final List linkedItems = this.oft.link(items); final Trace trace = this.oft.trace(linkedItems); final List filteredIds = trace.getItems() // From 06d1476cc3a6e274286f6ad13015301ce913a5ba Mon Sep 17 00:00:00 2001 From: redcatbear Date: Tue, 9 Oct 2018 21:27:16 +0200 Subject: [PATCH 56/60] #165: Added missing license headers. --- .../cli/commands/ConvertCommand.java | 24 ++++++++++++++++++- .../openfasttrace/core/OftRunner.java | 24 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java index 3fade694..31bb4fef 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java @@ -1,6 +1,28 @@ package org.itsallcode.openfasttrace.cli.commands; +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + import java.util.List; import org.itsallcode.openfasttrace.ExportSettings; @@ -46,4 +68,4 @@ private ExportSettings createExportSettingsFromArguments() .outputFormat(this.arguments.getOutputFormat()) // .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java index a2bf7c58..60f6f6fa 100644 --- a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java +++ b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java @@ -1,5 +1,27 @@ package org.itsallcode.openfasttrace.core; +/*- + * #%L + * OpenFastTrace + * %% + * Copyright (C) 2016 - 2018 itsallcode.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -106,4 +128,4 @@ public void reportToPath(final Trace trace, final Path outputPath, { new ReportService().reportTraceToPath(trace, outputPath, settings); } -} \ No newline at end of file +} From 6eed764f8dea245c4e88f9ab02372365a436fd5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=A4r?= Date: Wed, 10 Oct 2018 08:38:36 +0200 Subject: [PATCH 57/60] Updated Mockito version. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0e177e50..9bd5c74b 100644 --- a/pom.xml +++ b/pom.xml @@ -73,7 +73,7 @@ org.mockito mockito-core - 2.18.3 + 2.23.0 test From 680ffe039cd403a7ede81245264f8ad8988dd226 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Wed, 10 Oct 2018 21:32:50 +0200 Subject: [PATCH 58/60] #165: Unified builder for settings, updated user guide and raised version to 2.0.0. --- doc/user_guide.md | 102 +++++++++++++----- pom.xml | 2 +- .../openfasttrace/ReportSettings.java | 17 ++- .../cli/commands/TraceCommand.java | 2 +- .../openfasttrace/TestReportSettings.java | 2 +- .../mode/ITestOftAsReporter.java | 6 +- .../report/TestReportService.java | 12 +-- .../report/plaintext/TestPlainTextReport.java | 6 +- 8 files changed, 105 insertions(+), 44 deletions(-) diff --git a/doc/user_guide.md b/doc/user_guide.md index 7e2587db..ab76ff04 100644 --- a/doc/user_guide.md +++ b/doc/user_guide.md @@ -420,59 +420,105 @@ Defaults to the platform standard if not given. If you are a software developer planning to integrate OFT into one of your programs or scripts, you will probably want to use the OFT API. -Below you find a few short examples of how to use the OFT API. For details check the JavaDoc documentation of the interfaces in the source code. - -* [org.itsallcode.openfasttrace.Converter](../src/main/java/org/itsallcoded/openfasttrace/Converter.java) -* [org.itsallcode.openfasttrace.Reporter](../src/main/java/org/itsallcoded/openfasttrace/Reporter.java) +Below you find a few short examples of how to use the OFT API. For details check the JavaDoc documentation of the interface [org.itsallcode.openfasttrace.Oft](../src/main/java/org/itsallcoded/openfasttrace/Oft.java) in the source code. ### Using OFT From Java The Java interface uses the "fluent programming" paradigm to make the code more compact and easy to read. -#### Using the Converter From Java +The steps that you need to program using the OFT API depend on whether you want to covert between requirement formats + + import -> export + +or run a report. + + import -> link -> trace -> report + +#### Converting File from Java -The following example code configures a `Converter` to read input form the relative paths `doc`, `src/main/java` and `src/main/test` and output the result to `/tmp/out.xml` in SpecObject format using Unix newlines. +The following example code use a OFT as a converter to read input form a path and exports it with the standard settings to a ReqM2 file. ```JAVA -import org.itsallcode.openfasttrace.Converter; -import org.itsallcode.openfasttrace.core.Newline; -import org.itsallcode.openfasttrace.mode.ConvertMode; +import org.itsallcode.openfasttrace.Oft; +import org.itsallcode.openfasttrace.core.SpecificationItem; +``` -final List inputs = Arrays.asList("doc", "src/main/java", "src/main/test"); -final Converter converter = new ConvertMode(); +Select input paths and import specification items from there: -converter.addInputs(inputs) - .setNewline(Newline.UNIX) - .convertToFileInFormat("/tmp/out.xml", "specobject"); +```JAVA +final List inputs = new ArrayList<>(); +inputs.add(Paths.get("/input/path")); +final Oft oft = Oft.create().addInputs(inputs); +final List items = oft.importItems(); ``` -#### Using the Tracer From Java +Export the items: -The example below shows how to read documents for the `doc` directory ignoring the artifact types `feat` and `dsn`. The collected specification items are then traced and finally output in a plain text report to STDOUT with verbosity level `ALL`. +```JAVA +oft.exportToPath(items, Paths.get("/output/path/export.oreqm")); +``` + +#### Tracing and Reporting From Java + +The example below shows how to use OFT as a reporter. ```JAVA -import org.itsallcode.openfasttrace.Reporter; +import org.itsallcode.openfasttrace.Oft; +import org.itsallcode.openfasttrace.core.LinkedSpecificationItem; +import org.itsallcode.openfasttrace.core.SpecificationItem; import org.itsallcode.openfasttrace.core.Trace; -import org.itsallcode.openfasttrace.mode.ReportMode; +``` + +The import is identical to the converter case: -final List inputs = Arrays.asList("doc"); -final List ignoreTypes = Arras.asList("feat", "dsn"); -final Reporter reporter = new ReportMode(); +```JAVA +final List inputs = new ArrayList<>(); +inputs.add(Paths.get("/input/path")); +final Oft oft = Oft.create().addInputs(inputs); +final List items = oft.importItems(); +``` -reporter.addInputs(inputs) - .ignoreArtifactTypes(ignoreTypes); +Now link the items together (i.e. make them navigable): -final Trace trace = reporter.trace(); +```JAVA +final List linkedItems = oft.link(items); +``` -reporter.setReportVerbosity(ReportVerbosity.ALL) - .reportToStdOutInFormat(trace, "plain"); +Run the tracer on the linked items: -if(trace.isAllCovered()) +```JAVA +final Trace trace = oft.trace(linkedItems); +``` + +Create a report from the trace: + +```JAVA +oft.reportToStdOut(trace); +``` + +You can also use the trace results in you own code: + +```JAVA +if (trace.hasNoDefects()) { - // do something + // ... do something } ``` +#### Configuring the Steps + +Import, export and report each have a overloaded variant that can be configured using the following classes + +* [org.itsallcode.openfasttrace.ImportSettings](../src/main/java/org/itsallcoded/openfasttrace/ImportSettings.java) +* [org.itsallcode.openfasttrace.ExportSettings](../src/main/java/org/itsallcoded/openfasttrace/ExportSettings.java) +* [org.itsallcode.openfasttrace.ReportSettings](../src/main/java/org/itsallcoded/openfasttrace/ReportSettings.java) + +Each of those classes comes with a builder which is called like this: + +```JAVA +ReportSettings settings = ReportSettings.builder().newline(Newline.UNIX).build(); +``` + ## Tool Support ### Tools for Authoring OFT Documents diff --git a/pom.xml b/pom.xml index 0fdc3f08..026424cf 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.itsallcode openfasttrace - 1.2.1 + 2.0.0 OpenFastTrace Free requirement tracking suite https://github.com/itsallcode/openfasttrace diff --git a/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java index c3379a39..d8ead882 100644 --- a/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java +++ b/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java @@ -92,7 +92,17 @@ public Newline getNewline() */ public static ReportSettings createDefault() { - return new Builder().build(); + return builder().build(); + } + + /** + * Create a builder for {@link ReportSettings} + * + * @return builder + */ + public static Builder builder() + { + return new Builder(); } /** @@ -105,6 +115,11 @@ public static class Builder public boolean showOrigin = false; ReportVerbosity verbosity = ReportVerbosity.FAILURE_DETAILS; + private Builder() + { + + } + /** * Create a new instance of {@link ReportSettings} * diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java index e56123b1..12c6fd11 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java @@ -87,7 +87,7 @@ private void report(final Oft oft, final Trace trace) private ReportSettings convertCommandLineArgumentsToReportSettings() { - return new ReportSettings.Builder() // + return ReportSettings.builder() // .verbosity(this.arguments.getReportVerbosity()) // .newline(this.arguments.getNewline()) // .showOrigin(this.arguments.getShowOrigin()) // diff --git a/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java index 26516d63..270d50bc 100644 --- a/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java +++ b/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java @@ -38,7 +38,7 @@ public class TestReportSettings @Before public void before() { - this.builder = new ReportSettings.Builder(); + this.builder = ReportSettings.builder(); } @Test diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java index 2b5b5bf6..93d049c1 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java @@ -73,8 +73,8 @@ private void assertStandardReportFileResult() throws IOException @Test public void testTraceWithReportVerbosityMinimal() throws IOException { - final ReportSettings settings = new ReportSettings.Builder() - .verbosity(ReportVerbosity.MINIMAL).build(); + final ReportSettings settings = ReportSettings.builder().verbosity(ReportVerbosity.MINIMAL) + .build(); this.oft.reportToPath(this.trace, this.outputFile, settings); assertOutputFileExists(true); assertOutputFileContentStartsWith("ok"); @@ -83,7 +83,7 @@ public void testTraceWithReportVerbosityMinimal() throws IOException @Test public void testTraceMacNewlines() throws IOException { - final ReportSettings settings = new ReportSettings.Builder() // + final ReportSettings settings = ReportSettings.builder() // .newline(Newline.OLDMAC) // .build(); this.oft.reportToPath(this.trace, this.outputFile, settings); diff --git a/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java b/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java index 163e646c..ae280090 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java @@ -61,8 +61,8 @@ public void prepareTest() @Test public void testReportPlainText() { - final ReportSettings settings = new ReportSettings.Builder() - .verbosity(ReportVerbosity.MINIMAL).build(); + final ReportSettings settings = ReportSettings.builder().verbosity(ReportVerbosity.MINIMAL) + .build(); this.service.reportTraceToStdOut(this.traceMock, settings); assertThat(this.systemOutRule.getLog(), equalTo("not ok\n")); } @@ -70,7 +70,7 @@ public void testReportPlainText() @Test public void testReportHtml() { - final ReportSettings settings = new ReportSettings.Builder().outputFormat("html") + final ReportSettings settings = ReportSettings.builder().outputFormat("html") .verbosity(ReportVerbosity.MINIMAL).build(); this.service.reportTraceToStdOut(this.traceMock, settings); assertThat(this.systemOutRule.getLog(), startsWith("")); @@ -79,7 +79,7 @@ public void testReportHtml() @Test(expected = IllegalArgumentException.class) public void testInvalidReportFormatThrowsIllegalArgumentException() { - final ReportSettings settings = new ReportSettings.Builder().outputFormat("invalid") + final ReportSettings settings = ReportSettings.builder().outputFormat("invalid") .verbosity(ReportVerbosity.QUIET).build(); this.service.reportTraceToStdOut(this.traceMock, settings); } @@ -89,8 +89,8 @@ public void testReportToIllegalPathThrowsReportExpection() throws IOException { final File readOnlyFile = this.temporaryFolder.newFile(); readOnlyFile.setReadOnly(); - final ReportSettings settings = new ReportSettings.Builder() - .verbosity(ReportVerbosity.QUIET).build(); + final ReportSettings settings = ReportSettings.builder().verbosity(ReportVerbosity.QUIET) + .build(); this.service.reportTraceToPath(this.traceMock, readOnlyFile.toPath(), settings); } } diff --git a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java index 2f2c74b9..dcb44340 100644 --- a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java +++ b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java @@ -63,8 +63,8 @@ public void prepareTest() public void testOutputStreamClosed() throws IOException { final OutputStream outputStreamMock = mock(OutputStream.class); - final ReportSettings settings = new ReportSettings.Builder() - .verbosity(ReportVerbosity.SUMMARY).build(); + final ReportSettings settings = ReportSettings.builder().verbosity(ReportVerbosity.SUMMARY) + .build(); new PlainTextReport(this.traceMock, settings).renderToStream(outputStreamMock); verify(outputStreamMock).close(); } @@ -117,7 +117,7 @@ private String getReportOutputWithNewline(final ReportVerbosity verbosity, final Newline newline, final boolean showOrigin) { final OutputStream outputStream = new ByteArrayOutputStream(); - final ReportSettings settings = new ReportSettings.Builder().verbosity(verbosity) + final ReportSettings settings = ReportSettings.builder().verbosity(verbosity) .newline(newline).showOrigin(showOrigin).build(); final Reportable report = new PlainTextReport(this.traceMock, settings); report.renderToStream(outputStream); From cc8bdbee22c26e73bce1a4f7b52228c7237f66d2 Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sat, 13 Oct 2018 13:53:01 +0200 Subject: [PATCH 59/60] #165: OftRunner is now stateless. --- doc/user_guide.md | 20 ++++----- .../openfasttrace/ImportSettings.java | 43 +++++++++++++++++++ .../org/itsallcode/openfasttrace/Oft.java | 18 -------- .../cli/commands/AbstractCommand.java | 8 ++-- .../openfasttrace/core/OftRunner.java | 22 +--------- .../openfasttrace/TestImportSettings.java | 24 +++++++++++ .../mode/ITestOftAsConverter.java | 5 ++- .../mode/ITestOftAsReporter.java | 5 ++- .../mode/ITestReporterWithFilter.java | 9 ++-- 9 files changed, 95 insertions(+), 59 deletions(-) diff --git a/doc/user_guide.md b/doc/user_guide.md index ab76ff04..419af2e4 100644 --- a/doc/user_guide.md +++ b/doc/user_guide.md @@ -436,7 +436,7 @@ or run a report. #### Converting File from Java -The following example code use a OFT as a converter to read input form a path and exports it with the standard settings to a ReqM2 file. +The following example code use a OFT as a converter that scans the current working directory recursively (default import setting) and exports the found artifacts with the standard settings to a ReqM2 file. ```JAVA import org.itsallcode.openfasttrace.Oft; @@ -446,10 +446,8 @@ import org.itsallcode.openfasttrace.core.SpecificationItem; Select input paths and import specification items from there: ```JAVA -final List inputs = new ArrayList<>(); -inputs.add(Paths.get("/input/path")); -final Oft oft = Oft.create().addInputs(inputs); -final List items = oft.importItems(); +final Oft oft = Oft.create(); +final List items = oft.importItems(settings); ``` Export the items: @@ -469,13 +467,15 @@ import org.itsallcode.openfasttrace.core.SpecificationItem; import org.itsallcode.openfasttrace.core.Trace; ``` -The import is identical to the converter case: +The import is similar to the converter case, except this time we add an input path explicitly for the sake of demonstration: ```JAVA -final List inputs = new ArrayList<>(); -inputs.add(Paths.get("/input/path")); -final Oft oft = Oft.create().addInputs(inputs); -final List items = oft.importItems(); +final ImportSettings settings = ImportSettings // + .builder() // + .addInputs("/input/path") // + .build; +final Oft oft = Oft.create(); +final List items = oft.importItems(settings); ``` Now link the items together (i.e. make them navigable): diff --git a/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java index 0d7c7022..ed35b966 100644 --- a/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java +++ b/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java @@ -1,5 +1,6 @@ package org.itsallcode.openfasttrace; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -29,15 +30,27 @@ public class ImportSettings { + private final List inputs; private final FilterSettings filter; private final List pathConfigs; protected ImportSettings(final Builder builder) { + this.inputs = builder.inputs; this.filter = builder.filter; this.pathConfigs = builder.pathConfigs; } + /** + * Get the list of paths to be scanned for importable artifacts + * + * @return list of input paths + */ + public List getInputs() + { + return this.inputs; + } + /** * Get the filter settings * @@ -82,6 +95,7 @@ public static Builder builder() */ public static class Builder { + private final List inputs = new ArrayList<>(); private FilterSettings filter = FilterSettings.createAllowingEverything(); private List pathConfigs = new ArrayList<>(); @@ -89,6 +103,35 @@ private Builder() { } + /** + * Add a list of input paths to be scanned for importable artifacts + * + * @param inputs + * input paths to be scanned + * @return this for fluent programming + */ + public Builder addInputs(final List inputs) + { + this.inputs.addAll(inputs); + return this; + } + + /** + * Add one or more input paths to be scanned for importable artifacts + * + * @param inputs + * input paths to be scanned + * @return this for fluent programming + */ + public Builder addInputs(final Path... inputs) + { + for (final Path input : inputs) + { + this.inputs.add(input); + } + return this; + } + /** * Set the filters to be used during import * diff --git a/src/main/java/org/itsallcode/openfasttrace/Oft.java b/src/main/java/org/itsallcode/openfasttrace/Oft.java index 8d249f31..ee32a0b3 100644 --- a/src/main/java/org/itsallcode/openfasttrace/Oft.java +++ b/src/main/java/org/itsallcode/openfasttrace/Oft.java @@ -32,24 +32,6 @@ */ public interface Oft { - /** - * Select one or more input files - * - * @param inputs - * input files - * @return a Converter instance for fluent programming - */ - public Oft addInputs(final Path... inputs); - - /** - * Select one or more input files - * - * @param inputs - * input files - * @return an {@link Oft} instance for fluent programming - */ - public Oft addInputs(final List inputs); - /** * Run an import with default settings * diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java index 130397ec..3c3fac00 100644 --- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java +++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java @@ -97,9 +97,11 @@ private void setTagFilter(final FilterSettings.Builder builder) protected List importItems() { - this.oft.addInputs(this.toPaths(this.arguments.getInputs())); - final ImportSettings importSettings = ImportSettings.builder() - .filter(createFilterSettingsFromArguments()).build(); + final ImportSettings importSettings = ImportSettings // + .builder() // + .addInputs(this.toPaths(this.arguments.getInputs())) // + .filter(createFilterSettingsFromArguments()) // + .build(); return this.oft.importItems(importSettings); } } \ No newline at end of file diff --git a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java index 60f6f6fa..2c467fd5 100644 --- a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java +++ b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java @@ -23,7 +23,6 @@ */ import java.nio.file.Path; -import java.util.ArrayList; import java.util.List; import org.itsallcode.openfasttrace.*; @@ -34,31 +33,12 @@ public class OftRunner implements Oft { - private final List inputs = new ArrayList<>(); - - @Override - public Oft addInputs(final Path... inputs) - { - for (final Path input : inputs) - { - this.inputs.add(input); - } - return this; - } - - @Override - public Oft addInputs(final List inputs) - { - this.inputs.addAll(inputs); - return this; - } - @Override public List importItems(final ImportSettings settings) { return createImporterService(settings) // .createImporter() // - .importAny(this.inputs) // + .importAny(settings.getInputs()) // .getImportedItems(); } diff --git a/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java index e14ca7fc..b209b4d0 100644 --- a/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java +++ b/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java @@ -27,6 +27,8 @@ import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.junit.Assert.assertThat; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import org.itsallcode.openfasttrace.importer.tag.config.PathConfig; @@ -38,6 +40,12 @@ */ public class TestImportSettings { + @Test + public void testInputListEmptyByDefault() + { + assertThat(ImportSettings.createDefault().getInputs(), emptyIterableOf(Path.class)); + } + @Test public void testDefaultFilter() { @@ -52,6 +60,22 @@ public void testDefaultPathConfigs() emptyIterableOf(PathConfig.class)); } + @Test + public void testAddInputList() + { + final Path[] expectedInputs = { Paths.get("/a/path"), Paths.get("/another/path") }; + assertThat(ImportSettings.builder().addInputs(Arrays.asList(expectedInputs)).build() + .getInputs(), containsInAnyOrder(expectedInputs)); + } + + @Test + public void testAddInputArray() + { + final Path[] expectedInputs = { Paths.get("/a/path"), Paths.get("/another/path") }; + assertThat(ImportSettings.builder().addInputs(expectedInputs).build().getInputs(), + containsInAnyOrder(expectedInputs)); + } + @Test public void testBuildWithFilter() { diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java index a2274bb4..0ec1521f 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java @@ -26,6 +26,7 @@ import java.io.UnsupportedEncodingException; import java.util.List; +import org.itsallcode.openfasttrace.ImportSettings; import org.itsallcode.openfasttrace.Oft; import org.itsallcode.openfasttrace.core.SpecificationItem; import org.junit.Before; @@ -46,8 +47,8 @@ public void setUp() throws UnsupportedEncodingException @Test public void testConvertToSpecobjectFile() throws IOException { - this.oft.addInputs(this.docDir); - final List items = this.oft.importItems(); + final ImportSettings settings = ImportSettings.builder().addInputs(this.docDir).build(); + final List items = this.oft.importItems(settings); this.oft.exportToPath(items, this.outputFile); assertStandardFileExportResult(); } diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java index 93d049c1..3f988d4e 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java @@ -51,8 +51,9 @@ public class ITestOftAsReporter extends AbstractOftTest public void setUp() throws UnsupportedEncodingException { perpareOutput(); - this.oft = Oft.create().addInputs(this.docDir); - final List items = this.oft.importItems(); + final ImportSettings settings = ImportSettings.builder().addInputs(this.docDir).build(); + this.oft = Oft.create(); + final List items = this.oft.importItems(settings); this.linkedItems = this.oft.link(items); this.trace = this.oft.trace(this.linkedItems); } diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java index e5abbb86..b8f9dfab 100644 --- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java +++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java @@ -70,7 +70,7 @@ public class ITestReporterWithFilter extends AbstractFileBasedTest public void before() throws IOException { writeTextFile(this.tempFolder.newFile("spec.md"), SPECIFICATION); - this.oft = Oft.create().addInputs(this.tempFolder.getRoot().toPath()); + this.oft = Oft.create(); } // [itest->dsn~filtering-by-tags-during-import~1] @@ -87,8 +87,11 @@ public void testFilterWithAtLeastOneMatchingTag() private List getIdsFromTraceWithFilterSettings(final FilterSettings filterSettings) { - final List items = this.oft - .importItems(ImportSettings.builder().filter(filterSettings).build()); + final ImportSettings importSettings = ImportSettings.builder() // + .addInputs(this.tempFolder.getRoot().toPath()) // + .filter(filterSettings) // + .build(); + final List items = this.oft.importItems(importSettings); final List linkedItems = this.oft.link(items); final Trace trace = this.oft.trace(linkedItems); final List filteredIds = trace.getItems() // From d30c90b8ae23f32053a6fd809029608fc9e0827b Mon Sep 17 00:00:00 2001 From: redcatbear Date: Sat, 13 Oct 2018 13:55:26 +0200 Subject: [PATCH 60/60] #165: Removed erroneous comment. --- .../java/org/itsallcode/openfasttrace/TestExportSettings.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java index b01575a1..731b26c9 100644 --- a/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java +++ b/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java @@ -30,10 +30,6 @@ import org.junit.Before; import org.junit.Test; -/** - * This class implements a parameter object to control the settings of OFT's - * export mode. - */ public class TestExportSettings { private ExportSettings.Builder builder;