From 01734251ba8b23253c8868f2daff039b7f62e5a0 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Thu, 6 Aug 2026 06:46:57 +0100 Subject: [PATCH] Refactor UIOption, AntOption, and MavenOption along with their collections to provide cleaner implementations for multi threaded use as well as a better division of responsibility. - Implemented Builders for UIOption and UIOption derived classes. - Adjusted UIOPtionCollection to utilize UIOption.Builder - Simplified ArgumentContext construction by creating the CommandLine instance within the context. - Adapted command line parsing to accept UIOptionCollection as the source of arguments. - added isNull() to CasedString to indicate when the string will be null. - Updated tools to utilize new UIOption builders and collections. --- .../main/java/org/apache/rat/CLIOption.java | 24 +- .../org/apache/rat/CLIOptionCollection.java | 13 +- .../java/org/apache/rat/OptionCollection.java | 75 +++--- .../apache/rat/OptionCollectionParser.java | 60 +++-- .../java/org/apache/rat/commandline/Arg.java | 4 +- .../rat/commandline/ArgumentContext.java | 41 +++- .../org/apache/rat/help/AbstractHelp.java | 7 +- .../main/java/org/apache/rat/ui/UIOption.java | 153 +++++++++++- .../org/apache/rat/ui/UIOptionCollection.java | 154 +++++++----- .../apache/rat/ui/UpdatableOptionGroup.java | 1 + .../org/apache/rat/utils/CasedString.java | 17 +- .../java/org/apache/rat/CLIOptionTest.java | 10 +- .../rat/OptionCollectionParserTest.java | 62 ++--- .../org/apache/rat/OptionCollectionTest.java | 5 +- .../java/org/apache/rat/ReporterTest.java | 226 ++++++++++-------- .../test/java/org/apache/rat/TestOption.java | 73 ++++++ .../org/apache/rat/commandline/ArgTests.java | 21 +- .../apache/rat/testhelpers/BaseOption.java | 61 +++++ .../rat/testhelpers/BaseOptionCollection.java | 36 +++ .../apache/rat/ui/ArgumentTrackerTest.java | 2 +- .../apache/rat/ui/UIOptionCollectionTest.java | 24 +- .../java/org/apache/rat/ui/UIOptionTest.java | 211 +++++++++++++++- .../java/org/apache/rat/anttasks/Help.java | 2 +- .../rat/anttasks/GeneratedReportTest.java | 6 +- .../apache/rat/anttasks/ReportOptionTest.java | 5 +- .../rat/documentation/options/AntOption.java | 77 +++++- .../options/AntOptionCollection.java | 105 ++++---- .../documentation/options/MavenOption.java | 69 +++++- .../options/MavenOptionCollection.java | 45 +--- .../rat/documentation/velocity/RatTool.java | 27 ++- .../apache/rat/tools/AntDocumentation.java | 9 +- .../org/apache/rat/tools/AntGenerator.java | 7 +- .../org/apache/rat/tools/MavenGenerator.java | 13 +- .../java/org/apache/rat/tools/Naming.java | 217 +++++++++-------- .../options/MavenOptionTest.java | 3 +- .../documentation/velocity/RatToolTest.java | 11 +- .../rat/tools/AntDocumentationTest.java | 8 +- 37 files changed, 1342 insertions(+), 542 deletions(-) create mode 100644 apache-rat-core/src/test/java/org/apache/rat/TestOption.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOption.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOptionCollection.java diff --git a/apache-rat-core/src/main/java/org/apache/rat/CLIOption.java b/apache-rat-core/src/main/java/org/apache/rat/CLIOption.java index 7b75cdb8e..395452158 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/CLIOption.java +++ b/apache-rat-core/src/main/java/org/apache/rat/CLIOption.java @@ -18,19 +18,21 @@ */ package org.apache.rat; +import java.util.function.Function; + import org.apache.commons.cli.Option; import org.apache.commons.lang3.StringUtils; import org.apache.rat.ui.ArgumentTracker; import org.apache.rat.ui.UIOption; -import org.apache.rat.ui.UIOptionCollection; +import org.apache.rat.utils.CasedString; /** * The CLI option definition. */ public final class CLIOption extends UIOption { - public CLIOption(final UIOptionCollection collection, final Option option) { - super(collection, option, ArgumentTracker.extractName(option)); + private CLIOption(final CLIBuilder builder) { + super(builder); } @Override @@ -70,4 +72,20 @@ public String getExample() { } return sb.toString(); } + + /** + * Builder for a CLI Option. + */ + public static class CLIBuilder extends UIOption.Builder { + + @Override + protected Function getNameFactory() { + return ArgumentTracker::extractName; + } + + @Override + protected CLIOption doBuild() { + return new CLIOption(this); + } + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/CLIOptionCollection.java b/apache-rat-core/src/main/java/org/apache/rat/CLIOptionCollection.java index 9abb0ca57..023f4ae97 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/CLIOptionCollection.java +++ b/apache-rat-core/src/main/java/org/apache/rat/CLIOptionCollection.java @@ -21,20 +21,23 @@ import org.apache.commons.cli.Option; import org.apache.rat.ui.UIOptionCollection; +/** + * The collection of CLI Options. + */ public final class CLIOptionCollection extends UIOptionCollection { /** The Help option */ static final Option HELP = new Option("?", "help", false, "Print help for the RAT command line interface and exit."); - /** The instance of the collection */ - public static final CLIOptionCollection INSTANCE = new CLIOptionCollection(); - - private CLIOptionCollection() { + /** + * Constructs the CLIOption collection. + */ + public CLIOptionCollection() { super(new Builder().uiOption(HELP)); } private static final class Builder extends UIOptionCollection.Builder { private Builder() { - super(CLIOption::new); + super(CLIOption.CLIBuilder::new); } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/OptionCollection.java b/apache-rat-core/src/main/java/org/apache/rat/OptionCollection.java index ccf5b40fe..076581a54 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/OptionCollection.java +++ b/apache-rat-core/src/main/java/org/apache/rat/OptionCollection.java @@ -51,6 +51,8 @@ import org.apache.rat.license.LicenseSetFactory; import org.apache.rat.report.Reportable; import org.apache.rat.report.claim.ClaimStatistic; +import org.apache.rat.ui.ArgumentTracker; +import org.apache.rat.ui.UIOptionCollection; import org.apache.rat.utils.DefaultLog; import org.apache.rat.utils.Log.Level; import org.apache.rat.walker.ArchiveWalker; @@ -68,6 +70,11 @@ private OptionCollection() { // do not instantiate } + /** + * The collection of UI Options. + */ + private static UIOptionCollection baseOptionCollection = new CLIOptionCollection(); + /** * The Option comparator to sort the help. */ @@ -122,8 +129,8 @@ public static ReportConfiguration parseCommands(final File workingDirectory, fin * Parses the standard options to create a ReportConfiguration. *

* This method is {@code synchronized} because it uses shared mutable state: - * the {@link Arg} enum's {@code OptionGroup} instances (whose {@code selected} - * field is mutated by {@link DefaultParser#parse}), and + * the {@link #baseOptionCollection}'s {@code OptionGroup} instances (whose {@code selected} + * field is mutated by {@link DefaultParser#parse(Options, String[])}), and * {@link org.apache.rat.commandline.Converters#FILE_CONVERTER} (whose * {@code workingDirectory} field is set during argument processing). * Without synchronization, parallel Maven reactor threads (e.g. {@code mvn -T4}) @@ -140,29 +147,23 @@ public static ReportConfiguration parseCommands(final File workingDirectory, fin */ public static synchronized ReportConfiguration parseCommands(final File workingDirectory, final String[] args, final Consumer helpCmd, final boolean noArgs) throws IOException { - Options opts = buildOptions(); - CommandLine commandLine; + ArgumentContext argumentContext; try { - commandLine = DefaultParser.builder().setDeprecatedHandler(DeprecationReporter.getLogReporter()) - .setAllowPartialMatching(true).build().parse(opts, args); + argumentContext = new ArgumentContext(workingDirectory, opts, args); } catch (ParseException e) { - DefaultLog.getInstance().error(e.getMessage()); - DefaultLog.getInstance().error("Please use the \"--help\" option to see a list of valid commands and options.", e); System.exit(1); return null; // dummy return (won't be reached) to avoid Eclipse complaint about possible NPE // for "commandLine" } + Arg.processLogLevel(argumentContext, baseOptionCollection); - ArgumentContext argumentContext = new ArgumentContext(workingDirectory, commandLine); - Arg.processLogLevel(argumentContext, CLIOptionCollection.INSTANCE); - - if (commandLine.hasOption(HELP)) { + if (argumentContext.getCommandLine().hasOption(HELP)) { helpCmd.accept(opts); return null; } - if (commandLine.hasOption(Arg.HELP_LICENSES.option())) { + if (argumentContext.getCommandLine().hasOption(Arg.HELP_LICENSES.option())) { new Licenses(createConfiguration(argumentContext), new PrintWriter(System.out, false, StandardCharsets.UTF_8)).printHelp(); return null; } @@ -188,25 +189,38 @@ public static synchronized ReportConfiguration parseCommands(final File workingD * @see #parseCommands(File, String[], Consumer, boolean) */ public static ReportConfiguration createConfiguration(final ArgumentContext argumentContext) { - argumentContext.processArgs(CLIOptionCollection.INSTANCE); - final ReportConfiguration configuration = argumentContext.getConfiguration(); - final CommandLine commandLine = argumentContext.getCommandLine(); - Optional