This is an automated email from the ASF dual-hosted git repository.

Claudenw pushed a commit to branch UIOption_update
in repository https://gitbox.apache.org/repos/asf/creadur-rat.git

commit 6f29248df310e451ee922a57291a0f258516ebef
Author: Claude Warren <[email protected]>
AuthorDate: Thu Aug 6 06:46:57 2026 +0100

    fixed tests
---
 .../src/main/java/org/apache/rat/CLIOption.java    |  24 ++-
 .../java/org/apache/rat/CLIOptionCollection.java   |  10 +-
 .../main/java/org/apache/rat/OptionCollection.java |  72 ++++---
 .../org/apache/rat/OptionCollectionParser.java     |  60 ++++--
 .../apache/rat/commandline/ArgumentContext.java    |  41 +++-
 .../java/org/apache/rat/help/AbstractHelp.java     |   7 +-
 .../src/main/java/org/apache/rat/ui/UIOption.java  | 153 ++++++++++++--
 .../java/org/apache/rat/ui/UIOptionCollection.java | 136 +++++++------
 .../org/apache/rat/ui/UpdatableOptionGroup.java    |   1 +
 .../java/org/apache/rat/utils/CasedString.java     |  14 +-
 .../test/java/org/apache/rat/CLIOptionTest.java    |  10 +-
 .../org/apache/rat/OptionCollectionParserTest.java |  62 +++++-
 .../java/org/apache/rat/OptionCollectionTest.java  |   5 +-
 .../src/test/java/org/apache/rat/ReporterTest.java | 226 ++++++++++++---------
 .../java/org/apache/rat/commandline/ArgTests.java  |  21 +-
 .../org/apache/rat/testhelpers/BaseOption.java     |  61 ++++++
 .../rat/testhelpers/BaseOptionCollection.java      |  36 ++++
 .../org/apache/rat/ui/ArgumentTrackerTest.java     |   2 +-
 .../org/apache/rat/ui/UIOptionCollectionTest.java  |  24 ++-
 .../test/java/org/apache/rat/ui/UIOptionTest.java  |   3 +-
 .../main/java/org/apache/rat/anttasks/Help.java    |   2 +-
 .../apache/rat/anttasks/GeneratedReportTest.java   |   6 +-
 .../org/apache/rat/anttasks/ReportOptionTest.java  |   5 +-
 .../rat/documentation/options/AntOption.java       |  76 ++++++-
 .../documentation/options/AntOptionCollection.java | 105 +++++-----
 .../rat/documentation/options/MavenOption.java     |  69 +++++--
 .../options/MavenOptionCollection.java             |  45 +---
 .../apache/rat/documentation/velocity/RatTool.java |  27 ++-
 .../org/apache/rat/tools/AntDocumentation.java     |   9 +-
 .../java/org/apache/rat/tools/AntGenerator.java    |   7 +-
 .../java/org/apache/rat/tools/MavenGenerator.java  |  13 +-
 .../src/main/java/org/apache/rat/tools/Naming.java | 129 ++++++------
 .../rat/documentation/options/MavenOptionTest.java |   3 +-
 .../rat/documentation/velocity/RatToolTest.java    |  11 +-
 .../org/apache/rat/tools/AntDocumentationTest.java |   8 +-
 35 files changed, 1012 insertions(+), 471 deletions(-)

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 7b75cdb8..39545215 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<CLIOption> {
 
-    public CLIOption(final UIOptionCollection<CLIOption> collection, final 
Option option) {
-        super(collection, option, ArgumentTracker.extractName(option));
+    private CLIOption(final CLIBuilder builder) {
+        super(builder);
     }
 
     @Override
@@ -70,4 +72,20 @@ public final class CLIOption extends UIOption<CLIOption> {
         }
         return sb.toString();
     }
+
+    /**
+     * Builder for a CLI Option.
+     */
+    public static class CLIBuilder extends UIOption.Builder<CLIOption, 
CLIBuilder> {
+
+        @Override
+        protected Function<Option, CasedString> 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 9abb0ca5..9b192b16 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,20 @@ package org.apache.rat;
 import org.apache.commons.cli.Option;
 import org.apache.rat.ui.UIOptionCollection;
 
+/**
+ * The collection of CLI Options.
+ */
 public final class CLIOptionCollection extends UIOptionCollection<CLIOption> {
     /** 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() {
+    public CLIOptionCollection() {
         super(new Builder().uiOption(HELP));
     }
 
     private static final class Builder extends 
UIOptionCollection.Builder<CLIOption, 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 2d4bdd63..55bbdf62 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
@@ -35,7 +35,6 @@ import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
 import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.DefaultParser;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
@@ -51,6 +50,8 @@ import org.apache.rat.help.Licenses;
 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 +69,11 @@ public final class OptionCollection {
         // do not instantiate
     }
 
+    /**
+     * The collection of UI Options.
+     */
+    private static UIOptionCollection baseOptionCollection = new 
CLIOptionCollection();
+
     /**
      * The Option comparator to sort the help.
      */
@@ -130,29 +136,23 @@ public final class OptionCollection {
      */
     public static ReportConfiguration parseCommands(final File 
workingDirectory, final String[] args,
                                                     final Consumer<Options> 
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;
         }
@@ -178,25 +178,38 @@ public final class OptionCollection {
      * @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<Option> dirOpt = 
CLIOptionCollection.INSTANCE.getSelected(Arg.DIR);
-        if (dirOpt.isPresent()) {
-            try {
-                
configuration.addSource(getReportable(commandLine.getParsedOptionValue(
-                        dirOpt.get()), configuration));
-            } catch (ParseException e) {
-                throw new ConfigurationException("Unable to set parse " + 
dirOpt.get(), e);
+        try {
+            argumentContext.processArgs(baseOptionCollection);
+            final ReportConfiguration configuration = 
argumentContext.getConfiguration();
+            final CommandLine commandLine = argumentContext.getCommandLine();
+            Optional<Option> dirOpt = 
baseOptionCollection.getSelected(Arg.DIR);
+            if (dirOpt.isPresent()) {
+                try {
+                    File directoryName = 
commandLine.getParsedOptionValue(dirOpt.get());
+                    configuration.addSource(getReportable(directoryName, 
configuration));
+                } catch (ParseException e) {
+                    throw new ConfigurationException("Unable to set parse " + 
dirOpt.get(), e);
+                }
             }
-        }
-        for (String s : commandLine.getArgs()) {
-            Reportable reportable = getReportable(new File(s), configuration);
-            if (reportable != null) {
-                configuration.addSource(reportable);
+            for (String s : commandLine.getArgs()) {
+                Reportable reportable = getReportable(new File(s), 
configuration);
+                if (reportable != null) {
+                    configuration.addSource(reportable);
+                }
+            }
+            return configuration;
+        } catch (RuntimeException e) {
+            try (PrintWriter pw = new 
PrintWriter(DefaultLog.getInstance().asWriter(Level.ERROR))) {
+                pw.println("Unable to create Configuration: " + 
e.getMessage());
+                pw.println("=== Command line options ===");
+                for (Option opt : 
argumentContext.getCommandLine().getOptions()) {
+                    String[] values = opt.getValues();
+                    pw.printf("   %s: %s%n", ArgumentTracker.extractKey(opt), 
values == null ? "" : String.join(", ", values));
+                }
             }
+            throw new ConfigurationException("Unable to create Configuration", 
e);
         }
-        return configuration;
+
     }
 
     /**
@@ -205,7 +218,8 @@ public final class OptionCollection {
      * @return the Options comprised of the Options defined in this class.
      */
     public static Options buildOptions() {
-        return CLIOptionCollection.INSTANCE.getOptions();
+        baseOptionCollection.resetSelected();
+        return baseOptionCollection.getOptions();
     }
 
     /**
diff --git 
a/apache-rat-core/src/main/java/org/apache/rat/OptionCollectionParser.java 
b/apache-rat-core/src/main/java/org/apache/rat/OptionCollectionParser.java
index 71bef61a..5d256141 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/OptionCollectionParser.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/OptionCollectionParser.java
@@ -32,10 +32,12 @@ import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.api.RatException;
 import org.apache.rat.commandline.Arg;
 import org.apache.rat.commandline.ArgumentContext;
 import org.apache.rat.help.Licenses;
 import org.apache.rat.report.Reportable;
+import org.apache.rat.ui.UIOption;
 import org.apache.rat.ui.UIOptionCollection;
 import org.apache.rat.utils.DefaultLog;
 
@@ -44,15 +46,21 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 /**
  * Uses the AbstractOptionCollection to parse the command line options.
  * Contains utility methods to ReportConfiguration from the options and an 
array of arguments.
+ *
+ * @param <T> The UIOption type that this parser is handeling.
  */
 @SuppressFBWarnings("EI_EXPOSE_REP2")
-public final class OptionCollectionParser {
+public final class OptionCollectionParser<T extends UIOption<T>> {
     /**
      * The OptionCollection that we are working with.
      */
-    private final UIOptionCollection<?> uiOptionCollection;
+    private final UIOptionCollection<T> uiOptionCollection;
 
-    public OptionCollectionParser(final UIOptionCollection<?> 
optionCollection) {
+    /**
+     * Constructor.
+     * @param optionCollection  The option collection to use for
+     */
+    public OptionCollectionParser(final UIOptionCollection<T> 
optionCollection) {
         this.uiOptionCollection = optionCollection;
     }
 
@@ -62,11 +70,10 @@ public final class OptionCollectionParser {
      * @param workingDirectory The directory to resolve relative file names 
against.
      * @param args the arguments to parse
      * @return the ArgumentContext for the process.
-     * @throws IOException on error.
-     * @throws ParseException on option parsing error.
+     * @throws RatException on error.
      */
     public ArgumentContext parseCommands(final File workingDirectory, final 
String[] args)
-            throws IOException, ParseException {
+            throws RatException {
         return parseCommands(workingDirectory, args, 
uiOptionCollection.getOptions());
     }
 
@@ -77,8 +84,7 @@ public final class OptionCollectionParser {
      * @return the CommandLine
      * @throws ParseException on option parsing error.
      */
-    //@VisibleForTesting
-    CommandLine parseCommandLine(final Options opts, final String[] args) 
throws ParseException {
+    public static CommandLine parseCommandLine(final Options opts, final 
String[] args) throws ParseException {
         try {
             return 
DefaultParser.builder().setDeprecatedHandler(DeprecationReporter.getLogReporter())
                     .setAllowPartialMatching(true).build().parse(opts, args);
@@ -89,6 +95,16 @@ public final class OptionCollectionParser {
         }
     }
 
+    // visible for testing
+    void printHelp(final ArgumentContext argumentContext) throws RatException {
+        try {
+            new Licenses(argumentContext.getConfiguration(),
+                    new 
PrintWriter(argumentContext.getConfiguration().getOutput().get(),
+                            false, StandardCharsets.UTF_8)).printHelp();
+        } catch (IOException e) {
+            throw new RatException("Unable to print help: " + e.getMessage(), 
e);
+        }
+    }
     /**
      * Parses the standard options to create a ReportConfiguration.
      *
@@ -96,22 +112,22 @@ public final class OptionCollectionParser {
      * @param args the arguments to parse.
      * @param options An Options object containing Apache command line options.
      * @return the ArgumentContext for the process.
-     * @throws IOException on error.
-     * @throws ParseException on option parsing error.
+     * @throws RatException on error.
      */
-    private ArgumentContext parseCommands(final File workingDirectory, final 
String[] args,
-                                                                       final 
Options options) throws IOException, ParseException {
-        CommandLine commandLine = parseCommandLine(options, args);
-        ArgumentContext argumentContext = new 
ArgumentContext(workingDirectory, commandLine);
-        Arg.processLogLevel(argumentContext, uiOptionCollection);
-        populateConfiguration(argumentContext);
-        if (uiOptionCollection.isSelected(Arg.HELP_LICENSES)) {
-            new Licenses(argumentContext.getConfiguration(),
-                    new 
PrintWriter(argumentContext.getConfiguration().getOutput().get(),
-                            false, StandardCharsets.UTF_8)).printHelp();
+    // visible for testing
+    ArgumentContext parseCommands(final File workingDirectory, final String[] 
args,
+                                                                       final 
Options options) throws RatException {
+        try {
+            ArgumentContext argumentContext = new 
ArgumentContext(workingDirectory, options, args);
+            Arg.processLogLevel(argumentContext, uiOptionCollection);
+            populateConfiguration(argumentContext);
+            if (uiOptionCollection.isSelected(Arg.HELP_LICENSES)) {
+                printHelp(argumentContext);
+            }
+            return argumentContext;
+        } catch (ParseException e) {
+            throw new RatException("Unable to parse command line: " + 
e.getMessage(), e);
         }
-
-        return argumentContext;
     }
 
     /**
diff --git 
a/apache-rat-core/src/main/java/org/apache/rat/commandline/ArgumentContext.java 
b/apache-rat-core/src/main/java/org/apache/rat/commandline/ArgumentContext.java
index d4374a57..cd6135db 100644
--- 
a/apache-rat-core/src/main/java/org/apache/rat/commandline/ArgumentContext.java
+++ 
b/apache-rat-core/src/main/java/org/apache/rat/commandline/ArgumentContext.java
@@ -20,9 +20,13 @@ package org.apache.rat.commandline;
 
 import java.io.File;
 
+import org.apache.commons.cli.AlreadySelectedException;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
+import org.apache.rat.OptionCollectionParser;
 import org.apache.rat.ReportConfiguration;
 import org.apache.rat.document.DocumentName;
 import org.apache.rat.ui.UIOptionCollection;
@@ -46,28 +50,51 @@ public final class ArgumentContext {
      * Creates a context with the specified configuration.
      * @param workingDirectory the directory from which relative file names 
will be resolved.
      * @param configuration The configuration that is being built.
-     * @param commandLine The command line that is building the configuration.
+     * @param opts the Options for the command line.
+     * @param args the arguments for the options.
+     * @throws ParseException if the options can not parse the arguments.
      */
-    public ArgumentContext(final File workingDirectory, final 
ReportConfiguration configuration, final CommandLine commandLine) {
+    public ArgumentContext(final File workingDirectory, final 
ReportConfiguration configuration, final Options opts, final String[] args)
+            throws ParseException {
         this.workingDirectory = DocumentName.builder(workingDirectory).build();
-        this.commandLine = commandLine;
+        this.commandLine = 
OptionCollectionParser.parseCommandLine(clearSelected(opts), args);
         this.configuration = configuration;
     }
 
     /**
      * Creates a context with an empty configuration.
      * @param workingDirectory The directory from which to resolve relative 
file names.
-     * @param commandLine The command line.
+     * @param opts the Options for the command line.
+     * @param args the arguments for the options.
+     * @throws ParseException if the options can not parse the arguments.
      */
-    public ArgumentContext(final File workingDirectory, final CommandLine 
commandLine) {
-        this(workingDirectory, new ReportConfiguration(), commandLine);
+    public ArgumentContext(final File workingDirectory, final Options opts, 
final String[] args) throws ParseException {
+        this(workingDirectory, new ReportConfiguration(), opts, args);
     }
 
+    /**
+     * Clears the group selections in the options.
+     * @param options the options to clear.
+     * @return the options with all selections cleared.
+     */
+    private static Options clearSelected(final Options options) {
+        for (Option opt : options.getOptions()) {
+            OptionGroup group = options.getOptionGroup(opt);
+            if (group != null) {
+                try {
+                    group.setSelected(null);
+                } catch (AlreadySelectedException e) {
+                    throw new RuntimeException("Unexpected error with null 
argument", e);
+                }
+            }
+        }
+        return options;
+    }
     /**
      * Process the arguments specified in this context.
      */
     public void processArgs(final UIOptionCollection<?> uiOptionCollection) {
-        Arg.processArgs(this,  uiOptionCollection);
+        Arg.processArgs(this, uiOptionCollection);
     }
 
     /**
diff --git 
a/apache-rat-core/src/main/java/org/apache/rat/help/AbstractHelp.java 
b/apache-rat-core/src/main/java/org/apache/rat/help/AbstractHelp.java
index 87952338..a1e4c4f0 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/help/AbstractHelp.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/help/AbstractHelp.java
@@ -54,6 +54,11 @@ public abstract class AbstractHelp {
     /** The version info for this instance */
     protected final VersionInfo versionInfo;
 
+    /**
+     * The collection of client options.
+     */
+    protected final CLIOptionCollection cliOptionCollection = new 
CLIOptionCollection();
+
     /**
      * Base class to perform help output.
      */
@@ -185,7 +190,7 @@ public abstract class AbstractHelp {
                     optBuf.append(END_OF_OPTION_MSG);
                 }
                 // check for default value
-                String defaultValue = 
CLIOptionCollection.INSTANCE.defaultValue(option);
+                String defaultValue = cliOptionCollection.defaultValue(option);
                 if (defaultValue != null) {
                     optBuf.append(format(" (Default value = %s)", 
defaultValue));
                 }
diff --git a/apache-rat-core/src/main/java/org/apache/rat/ui/UIOption.java 
b/apache-rat-core/src/main/java/org/apache/rat/ui/UIOption.java
index fa5533bc..9d04f67d 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/ui/UIOption.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/ui/UIOption.java
@@ -21,7 +21,9 @@ package org.apache.rat.ui;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -38,27 +40,37 @@ import static java.lang.String.format;
  * @param <T> the concrete implementation of AbstractOption.
  */
 public abstract class UIOption<T extends UIOption<T>> {
-    /** The pattern to match CLI options in text */
+    /**
+     * The pattern to match CLI options in text
+     */
     protected static final Pattern PATTERN = 
Pattern.compile("-?-([A-Za-z0-9]+-?)+"); // NOSONAR
-    /** The actual UI-specific name for the option */
+    /**
+     * The actual UI-specific name for the option
+     */
     protected final Option option;
-    /** The name for the option */
+    /**
+     * The name for the option
+     */
     protected final CasedString name;
-    /** The argument type for this option */
+    /**
+     * The argument type for this option
+     */
     protected final OptionCollection.ArgumentType argumentType;
-    /** The AbstractOptionCollection associated with this AbstractOption */
+    /**
+     * The AbstractOptionCollection associated with this AbstractOption
+     */
     protected final UIOptionCollection<T> optionCollection;
 
     /**
      * Constructor.
      *
-     * @param option The CLI option
-     * @param name the UI-specific name for the option
+     * @param builder UIOption builder.
      */
-    protected <C extends UIOptionCollection<T>> UIOption(final C 
optionCollection, final Option option, final CasedString name) {
-        this.optionCollection = optionCollection;
-        this.option = option;
-        this.name = name;
+    protected UIOption(final Builder<T, ?> builder) {
+        this.optionCollection = builder.optionCollection;
+        this.option = builder.option;
+        this.name = builder.name();
+
         OptionCollection.ArgumentType argType;
         if (option.hasArg()) {
             if (option.getArgName() == null) {
@@ -77,6 +89,20 @@ public abstract class UIOption<T extends UIOption<T>> {
         this.argumentType = argType;
     }
 
+    @Override
+    public boolean equals(final Object o) {
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        UIOption<?> uiOption = (UIOption<?>) o;
+        return getOption().equals(uiOption.getOption()) && 
name.equals(uiOption.name) && argumentType == uiOption.argumentType;
+    }
+
+    @Override
+    public int hashCode() {
+        return getName().hashCode();
+    }
+
     /**
      * Gets the AbstractOptionCollection that this option is a member of.
      * @return the AbstractOptionCollection that this option is a member of.
@@ -240,6 +266,109 @@ public abstract class UIOption<T extends UIOption<T>> {
      * @return the deprecated string if the option is deprecated, or an empty 
string otherwise.
      */
     public final String getDeprecated() {
-        return  option.isDeprecated() ? 
cleanup(StringUtils.defaultIfEmpty(option.getDeprecated().toString(), 
StringUtils.EMPTY)) : StringUtils.EMPTY;
+        return option.isDeprecated() ? 
cleanup(StringUtils.defaultIfEmpty(option.getDeprecated().toString(), 
StringUtils.EMPTY)) : StringUtils.EMPTY;
+    }
+
+    /**
+     * The abstract UIOption Builder.
+     * @param <T> the concrete type of the UIOption this builder produces.
+     * @param <B> the concrete type of this builder.
+     */
+    public abstract static class Builder<T extends UIOption<T>, B extends 
Builder<T, B>> {
+        /**
+         * The collection to add the new UI Option to.
+         */
+        private UIOptionCollection<T> optionCollection;
+        /**
+         * THe base option that is being mapped.
+         */
+        private Option option;
+
+        /**
+         * Constructor.
+         */
+        protected Builder() {
+        }
+
+        /**
+         * Returns a function to convert an Option to a CasedString that is 
the native name for the option.
+         * @return a function to convert an Option to a CasedString that is 
the native name for the option.
+         */
+        protected abstract Function<Option, CasedString> getNameFactory();
+
+        /**
+         * Gets the option.
+         * @return the option or {@code null} if the option is not set.
+         */
+        protected final Option option() {
+            return option;
+        }
+
+        /**
+         * Gets UI name for the .
+         * @return the option or {@code null} if the option is not set.
+         */
+        protected final CasedString name() {
+            return option == null ? null : getNameFactory().apply(option);
+        }
+
+        /**
+         * Gets the UIOptionCollection that the options will be added to.
+         * @return UIOptionCollection that the options will be added to.
+         */
+        protected final UIOptionCollection<T> optionCollection() {
+            return optionCollection;
+        }
+
+        /**
+         * Returns this builder cast to the builder type.
+         * Useful for implementing fluent builders.
+         * @return this builder.
+         */
+        protected final B self() {
+            return (B) this;
+        }
+
+        /**
+         * Sets the UIOptionCollection that the UIOptions will be added to.
+         * @param optionCollection the UIOptionCollection that the UIOptions 
will be added to.
+         * @return this
+         */
+        public B optionCollection(final UIOptionCollection<T> 
optionCollection) {
+            this.optionCollection = optionCollection;
+            return self();
+        }
+
+        /**
+         * Sets the Option that the UIOption will be generated from.
+         * @param option to build the UIOption from.
+         * @return this
+         */
+        public B option(final Option option) {
+            this.option = option;
+            return self();
+        }
+
+        /**
+         * Executes the final build.  Implemetation should use the builder to 
construct an instance of {@link <></>}
+         * @return An instance of the UIOption.
+         * @throws IllegalArgumentException if values are not set correctly.
+         */
+        protected abstract T doBuild() throws IllegalArgumentException;
+
+        /**
+         * Builds the UIOption.
+         * @return the UIOption.
+         * @throws IllegalArgumentException if values are not set correctly.
+         */
+        public final T build() throws IllegalArgumentException {
+            Objects.requireNonNull(optionCollection, "OptionCollection may not 
be null");
+            Objects.requireNonNull(option, "Option may not be null");
+            CasedString name = name();
+            if (name == null || name.isNull()) {
+                throw new IllegalArgumentException("name may not be null or 
contain a null value");
+            }
+            return doBuild();
+        }
     }
 }
diff --git 
a/apache-rat-core/src/main/java/org/apache/rat/ui/UIOptionCollection.java 
b/apache-rat-core/src/main/java/org/apache/rat/ui/UIOptionCollection.java
index e88f8440..9d1a3e80 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/ui/UIOptionCollection.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/ui/UIOptionCollection.java
@@ -26,9 +26,10 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.TreeMap;
-import java.util.function.BiFunction;
+import java.util.function.Supplier;
 import java.util.stream.Stream;
 
+import org.apache.commons.cli.AlreadySelectedException;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.apache.rat.Defaults;
@@ -37,7 +38,7 @@ import org.apache.rat.utils.Log;
 
 /**
  * A collection of options supported by the UI. This includes RAT options and 
UI specific options.
- * @param <T> the AbstractOption implementation.
+ * @param <T> the UIOption implementation.
  */
 public class UIOptionCollection<T extends UIOption<T>> {
     /** map of ARG to the associated UpdatableOptionGroup */
@@ -52,19 +53,13 @@ public class UIOptionCollection<T extends UIOption<T>> {
      */
     private final Map <Option, String> defaultValues;
 
-    /**
-     * The function to generate a concrete BaseOption instance.
-     */
-    private final BiFunction<UIOptionCollection<T>, Option, T> mapper;
-
     /**
      * Construct the UIOptionCollection from the builder.
-     * @param builder the builder to build from.
+     * @param builder the Builder to build from.
      */
     protected UIOptionCollection(final Builder<T, ?> builder) {
-        Objects.requireNonNull(builder.mapper, "Builder.mapper");
+        Objects.requireNonNull(builder.uiOptionBuilderSupplier, 
"Builder.mapper");
         argMap = new TreeMap<>();
-        mapper = builder.mapper;
         supportedRatOptions = new UpdatableOptionGroupCollection();
 
         for (Arg arg : Arg.values()) {
@@ -75,15 +70,28 @@ public class UIOptionCollection<T extends UIOption<T>> {
             supportedRatOptions.findGroups(opt).forEach(group -> 
group.disableOption(opt));
         }
         uiOptions = new HashMap<>();
+        UIOption.Builder<T, ?> optBuilder = 
builder.uiOptionBuilderSupplier.get();
+        optBuilder.optionCollection(this);
         supportedRatOptions.options().getOptions()
-                .forEach(option -> uiOptions.put(option, mapper.apply(this, 
option)));
+                .forEach(option -> uiOptions.put(option, 
optBuilder.option(option).build()));
         builder.uiOptions.stream().filter(option -> 
!uiOptions.containsKey(option))
-                .forEach(option -> uiOptions.put(option, mapper.apply(this, 
option)));
+                .forEach(option -> uiOptions.put(option, 
optBuilder.option(option).build()));
         defaultValues = new HashMap<>(builder.defaultValues);
     }
 
     /**
-     * Checks if an Arg is selected.
+     * Extracts the UI based name string for an option.
+     * The default implementation return the string returned by {@link 
ArgumentTracker#extractKey(Option)}
+     *
+     * @param option the option to create the name for.
+     * @return the name for the option in the UICollection name, may be the 
same as the option name.
+     */
+    public String rename(final Option option) {
+        return ArgumentTracker.extractKey(option);
+    }
+
+    /**
+     * Checks if an {@link Arg} is selected.
      * @param arg the Arg to check.
      * @return {@code true} if the arg is selected.
      */
@@ -93,8 +101,8 @@ public class UIOptionCollection<T extends UIOption<T>> {
     }
 
     /**
-     * Gets the selected Option for the arg.
-     * @param arg the arg to check.
+     * Gets the selected Option for an Arg.
+     * @param arg the Arg to get the Option for..
      * @return an Optional containing the selected option, or an empty 
Optional if none was selected.
      */
     public final Optional<Option> getSelected(final Arg arg) {
@@ -110,43 +118,57 @@ public class UIOptionCollection<T extends UIOption<T>> {
         return Optional.empty();
     }
 
+    /**
+     * Resets the groups in the Args so that they are unused and ready to 
detect the next set of arguments.
+     */
+    public void resetSelected() {
+        argMap.values().forEach(uog -> {
+            try {
+                uog.setSelected(null);
+            } catch (AlreadySelectedException e) {
+                throw new RuntimeException(e);
+            }
+        });
+    }
+
     /**
      * Gets the collection of unsupported Options.
-     * @return the Options comprised for the unsupported options.
+     * @return the Options comprising the unsupported options.
      */
     public final Options getUnsupportedOptions() {
         return supportedRatOptions.unsupportedOptions();
     }
 
     /**
-     * Gets the UiOption instance for the Option.
+     * Gets the UIOption instance for the Option.
      * @param option the option to find the instance of.
-     * @return a UIOption instance that wraps the option.
+     * @return an Optional containing the UIOption for the option, or an empty 
Optional if the option is not in the UI.
      */
     public final Optional<T> getMappedOption(final Option option) {
         return Optional.ofNullable(uiOptions.get(option));
     }
 
     /**
-     * Gets an Options that contains the RAT Arg defined Option instances that 
are understood by this collection.
+     * Gets an Options that contains the Options and OptionGroups are 
understood by this collection.
      * OptionGroups are registered in the resulting Options object.
-     * @return an Options that contains the RAT Arg defined Option instances 
that are understood by this collection.
+     * @return an Options that contains the {@link Arg} defined Option 
instances that are understood by this collection as well as
+     * any additional custom Options.
      */
     public final Options getOptions() {
         return supportedRatOptions.options().addOptions(additionalOptions());
     }
 
     /**
-     * Gets the Stream of AbstractOption implementations understood by this 
collection.
-     * @return the Stream of AbstractOption implementations understood by this 
collection.
+     * Gets the Stream of UIOption implementations understood by this 
collection.
+     * @return the Stream of UIOption implementations understood by this 
collection.
      */
     public final Stream<T> getMappedOptions() {
         return uiOptions.values().stream();
     }
 
     /**
-     * Gets a map client option name to specified AbstractOption 
implementation.
-     * @return a map client option name to specified AbstractOption 
implementation
+     * Gets a map client option name to the specified UIOption implementation.
+     * @return a map client option name to thge specified UIOption 
implementation.
      */
     public final Map<String, T> getOptionMap() {
         Map<String, T> result = new TreeMap<>();
@@ -155,8 +177,8 @@ public class UIOptionCollection<T extends UIOption<T>> {
     }
 
     /**
-     * Gets the additional options understood by this collection.
-     * @return the additional options understood by this collection.
+     * Gets the additional Options understood by this collection.
+     * @return the additional Options understood by this collection.
      */
     public final Options additionalOptions() {
         Options options = new Options();
@@ -176,11 +198,11 @@ public class UIOptionCollection<T extends UIOption<T>> {
     }
 
     /**
-     * Builder for a BaseOptionCollection.
-     * @param <T> the concreate type of the BaseOption.
-     * @param <S> the concrete type being built.
+     * Builder for a UIOptionCollection.
+     * @param <T> the concreate type of the UIOption.
+     * @param <B> the concrete type the Builder.
      */
-    protected static class Builder<T extends UIOption<T>, S extends Builder<T, 
S>> {
+    protected static class Builder<T extends UIOption<T>, B extends Builder<T, 
B>> {
         /** set of additional UI specific options */
         private final List<Option> uiOptions;
         /**
@@ -191,13 +213,13 @@ public class UIOptionCollection<T extends UIOption<T>> {
         /** The list of unsupported RAT options. */
         protected final List<Option> unsupportedRatOptions;
         /** The function to convert an option into a UIOption. */
-        private final BiFunction<UIOptionCollection<T>, Option, T> mapper;
+        private final Supplier<UIOption.Builder<T, ?>> uiOptionBuilderSupplier;
 
         /**
-         * Constructor for the builder.
+         * Constructor for the UI option collection builder.
          */
-        protected Builder(final BiFunction<UIOptionCollection<T>, Option, T> 
mapper) {
-            this.mapper = mapper;
+        protected Builder(final Supplier<UIOption.Builder<T, ?>> 
uiOptionBiulderSupplier) {
+            this.uiOptionBuilderSupplier = uiOptionBiulderSupplier;
             uiOptions = new ArrayList<>();
             defaultValues = new HashMap<>();
             unsupportedRatOptions = new ArrayList<>();
@@ -209,59 +231,51 @@ public class UIOptionCollection<T extends UIOption<T>> {
         }
 
         /**
-         * Build the UIOptionCollection.
-         * @return the UIOptionCollection.
-         */
-        public UIOptionCollection<T> build() {
-            return new UIOptionCollection<>(this);
-        }
-
-        /**
-         * Returns this cast to {@code <S>} class.
-         * @return this as {@code <S>} class.
+         * Returns this cast to {@code <B>} class.
+         * @return this as {@code <B>} class.
          */
-        protected final S self() {
-            return (S) this;
+        protected final B self() {
+            return (B) this;
         }
 
         /**
-         * Add a UI option to the collection.
-         * @param uiOption the UI Option to add.
+         * Add an Option to the collection as a UIOption.
+         * @param option the Option to add.
          * @return this
          */
-        public S uiOption(final Option uiOption) {
-            uiOptions.add(uiOption);
+        public B uiOption(final Option option) {
+            uiOptions.add(option);
             return self();
         }
 
         /**
-         * Add a UI options to the collection.
-         * @param uiOption the UIOptions ({@code <T>} objects) to add.
+         * Add multiple Option instances to the collection as UIOptions.
+         * @param options the Option instances to add.
          * @return this
          */
-        public S uiOptions(final Option... uiOption) {
-            uiOptions.addAll(Arrays.asList(uiOption));
+        public B uiOptions(final Option... options) {
+            uiOptions.addAll(Arrays.asList(options));
             return self();
         }
 
         /**
-         * Register an option as unsupported.
-         * @param option the option that is not be supported. This should be 
an option in the
+         * Register an Option as unsupported.
+         * @param option the Option that is not be supported. This should be 
an option in the
          * {@link Arg} collection.
          * @return this
          */
-        public S unsupported(final Option option) {
+        public B unsupported(final Option option) {
             unsupportedRatOptions.add(option);
             return self();
         }
 
         /**
-         * Register multiple options as unsupported.
+         * Register multiple Options as unsupported.
          * Will ignore all the options associated with the specified Arg.
          * @param arg The Arg to ignore.
          * @return this
          */
-        public S unsupported(final Arg arg) {
+        public B unsupported(final Arg arg) {
             unsupportedRatOptions.addAll(arg.group().getOptions());
             return self();
         }
@@ -272,7 +286,7 @@ public class UIOptionCollection<T extends UIOption<T>> {
          * @param value the value for the option.
          * @return this
          */
-        public S defaultValue(final Option option, final String value) {
+        public B defaultValue(final Option option, final String value) {
             defaultValues.put(option, value);
             return self();
         }
@@ -283,7 +297,7 @@ public class UIOptionCollection<T extends UIOption<T>> {
          * @param value the value for the option.
          * @return this
          */
-        public S defaultValue(final Arg arg, final String value) {
+        public B defaultValue(final Arg arg, final String value) {
             return defaultValue(arg.option(), value);
         }
     }
diff --git 
a/apache-rat-core/src/main/java/org/apache/rat/ui/UpdatableOptionGroup.java 
b/apache-rat-core/src/main/java/org/apache/rat/ui/UpdatableOptionGroup.java
index 42181e99..7e6948c1 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/ui/UpdatableOptionGroup.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/ui/UpdatableOptionGroup.java
@@ -65,6 +65,7 @@ public final class UpdatableOptionGroup extends OptionGroup {
     public Stream<Option> getDisableOptions() {
         return disabledOptions.stream();
     }
+
     /**
      * Reset the group so that all disabled options are re-enabled.
      */
diff --git 
a/apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java 
b/apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java
index 72478bdf..cdd2f134 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java
@@ -62,7 +62,7 @@ public final class CasedString {
      * @param segments the segments of the string.
      */
     public CasedString(final StringCase stringCase, final String[] segments) {
-        this.segments = segments;
+        this.segments = segments.length == 0 ? StringCase.NULL_SEGMENT : 
segments;
         this.stringCase = stringCase;
     }
 
@@ -72,7 +72,15 @@ public final class CasedString {
      * @return the new CasedString.
      */
     public CasedString as(final StringCase stringCase) {
-        return stringCase.name.equals(this.stringCase.name) ? this : new 
CasedString(stringCase, Arrays.copyOf(this.segments, this.segments.length));
+        return stringCase.name.equals(this.stringCase.name) ? this : new 
CasedString(stringCase, copySegments());
+    }
+
+    private String[] copySegments() {
+        return this.segments.length == 0 ? StringCase.NULL_SEGMENT : 
Arrays.copyOf(this.segments, this.segments.length);
+    }
+
+    public boolean isNull() {
+        return segments.length == 0;
     }
 
     /**
@@ -103,7 +111,7 @@ public final class CasedString {
             return false;
         }
         CasedString that = (CasedString) o;
-        return Objects.deepEquals(getSegments(), that.getSegments()) && 
Objects.equals(stringCase, that.stringCase);
+        return Objects.equals(stringCase, that.stringCase) && 
Objects.deepEquals(getSegments(), that.getSegments());
     }
 
     @Override
diff --git a/apache-rat-core/src/test/java/org/apache/rat/CLIOptionTest.java 
b/apache-rat-core/src/test/java/org/apache/rat/CLIOptionTest.java
index 028c25fd..de02cee6 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/CLIOptionTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/CLIOptionTest.java
@@ -26,10 +26,12 @@ import java.io.File;
 import static org.assertj.core.api.Assertions.assertThat;
 
 class CLIOptionTest {
-    final CLIOption optionA = new CLIOption(CLIOptionCollection.INSTANCE, new 
Option("a", false, "short key"));
-    final CLIOption optionB = new CLIOption(CLIOptionCollection.INSTANCE, 
Option.builder("b").longOpt("bee").hasArg().desc("two key").build());
-    final CLIOption optionC = new CLIOption(CLIOptionCollection.INSTANCE, 
Option.builder().longOpt("sea").hasArgs().type(File.class).desc("long 
key").build());
-    final CLIOption optionD = new CLIOption(CLIOptionCollection.INSTANCE, 
Option.builder().longOpt("dee").hasArgs().argName("dede").desc("long 
key").build());
+    final CLIOptionCollection cliOptionCollection = new CLIOptionCollection();
+    final CLIOption.CLIBuilder builder = new 
CLIOption.CLIBuilder().optionCollection(cliOptionCollection);
+    final CLIOption optionA = builder.option(new Option("a", false, "short 
key")).build();
+    final CLIOption optionB = 
builder.option(Option.builder("b").longOpt("bee").hasArg().desc("two 
key").build()).build();
+    final CLIOption optionC = 
builder.option(Option.builder().longOpt("sea").hasArgs().type(File.class).desc("long
 key").build()).build();
+    final CLIOption optionD = 
builder.option(Option.builder().longOpt("dee").hasArgs().argName("dede").desc("long
 key").build()).build();
 
     @Test
     void getText() {
diff --git 
a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionParserTest.java 
b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionParserTest.java
index f18ee2ab..3fb8f4ff 100644
--- 
a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionParserTest.java
+++ 
b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionParserTest.java
@@ -19,19 +19,26 @@
 package org.apache.rat;
 
 import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
+import org.apache.rat.api.RatException;
 import org.apache.rat.commandline.ArgumentContext;
+import org.apache.rat.testhelpers.TestingLog;
+import org.apache.rat.ui.ArgumentTracker;
 import org.apache.rat.ui.UIOption;
 import org.apache.rat.ui.UIOptionCollection;
 import org.apache.rat.utils.CasedString;
+import org.apache.rat.utils.DefaultLog;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.CleanupMode;
 import org.junit.jupiter.api.io.TempDir;
 
 import java.io.IOException;
 import java.nio.file.Path;
+import java.util.function.Function;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 class OptionCollectionParserTest {
 
@@ -39,10 +46,10 @@ class OptionCollectionParserTest {
     static Path testPath;
 
     private final TestOptionCollection optionCollection = new 
TestOptionCollection();
-    private final OptionCollectionParser underTest = new 
OptionCollectionParser(optionCollection);
+    private final OptionCollectionParser<TestOption> underTest = new 
OptionCollectionParser<>(optionCollection);
 
     @Test
-    void parseCommands() throws IOException, ParseException {
+    void parseCommands() throws RatException {
         String[] args = {"arg1", "arg2"};
         ArgumentContext ctxt = underTest.parseCommands(testPath.toFile(), 
args);
         assertThat(ctxt.getCommandLine().getArgList()).containsExactly(args);
@@ -55,6 +62,35 @@ class OptionCollectionParserTest {
         assertThat(ctxt.getCommandLine().getArgList()).containsExactly(args);
     }
 
+    @Test
+    void parseCommandLineParseExceptionTest() {
+        Options options = new Options();
+        options.addOption(Option.builder("req").required().build());
+        TestingLog testingLog = new TestingLog();
+        try {
+            DefaultLog.setInstance(testingLog);
+            assertThatThrownBy(() -> underTest.parseCommandLine(options, new 
String[0]))
+                    .isInstanceOf(ParseException.class);
+        } finally {
+            DefaultLog.setInstance(null);
+        }
+        assertThat(testingLog.getCaptured()).containsOnlyOnce("Please use the 
\"--help\" option to see a list of valid commands and options.");
+    }
+
+    @Test
+    void printHelpExceptionTest() throws ParseException {
+        Options options = new Options();
+        ReportConfiguration cfg = new ReportConfiguration();
+        ArgumentContext ctxt = new ArgumentContext(testPath.toFile(), cfg, 
options, new String[0]);
+        cfg.setOut(new ReportConfiguration.IODescriptor("Bad Supplier", () -> 
{ throw new IOException("Bad Supplier");}));
+        assertThatThrownBy(() -> underTest.printHelp(ctxt))
+                .isInstanceOf(RatException.class)
+                .hasMessageContaining("Unable to print help: Bad Supplier");
+    }
+
+    /**
+     * A UIOption implementation to support testing.
+     */
     static class TestOption extends UIOption<TestOption> {
 
         /**
@@ -63,8 +99,8 @@ class OptionCollectionParserTest {
          * @param optionCollection the collection the UIOption belongs to.
          * @param option           The CLI option
          */
-        protected <C extends UIOptionCollection<TestOption>> TestOption(C 
optionCollection, Option option) {
-            super(optionCollection, option, new 
CasedString(CasedString.StringCase.CAMEL, option.getKey()));
+        protected <C extends UIOptionCollection<TestOption>> 
TestOption(TestOptionBuilder builder) {
+            super(builder);
         }
 
         @Override
@@ -81,8 +117,24 @@ class OptionCollectionParserTest {
         public String getText() {
             return "text for " + option.toString();
         }
+
+        public static class TestOptionBuilder extends 
UIOption.Builder<TestOption, TestOptionBuilder> {
+
+            @Override
+            protected Function<Option, CasedString> getNameFactory() {
+                return ArgumentTracker::extractName;
+            }
+
+            @Override
+            protected TestOption doBuild() {
+                return new TestOption(this);
+            }
+        }
     }
 
+    /**
+     * A UIOptionCollection implementation for testing.  Contains TestOptions.
+     */
     static class TestOptionCollection extends UIOptionCollection<TestOption> {
         /**
          * Construct the UIOptionCollection from the builder.
@@ -93,7 +145,7 @@ class OptionCollectionParserTest {
 
         static class TestCollectionBuilder extends 
UIOptionCollection.Builder<TestOption, TestCollectionBuilder> {
             TestCollectionBuilder() {
-                super(TestOption::new);
+                super(TestOption.TestOptionBuilder::new);
             }
         }
     }
diff --git 
a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java 
b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
index 070484f2..ccc7e3bb 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
@@ -30,8 +30,6 @@ import java.nio.file.Path;
 import java.util.Locale;
 import java.util.Map;
 import java.util.TreeMap;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.DefaultParser;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.lang3.tuple.Pair;
@@ -220,8 +218,7 @@ public class OptionCollectionTest {
     @Test
     public void testDefaultConfiguration() throws ParseException {
         String[] empty = {};
-        CommandLine cl = new 
DefaultParser().parse(OptionCollection.buildOptions(), empty);
-        ArgumentContext context = new ArgumentContext(new File("."), cl);
+        ArgumentContext context = new ArgumentContext(new File("."), 
OptionCollection.buildOptions(), empty);
         ReportConfiguration config = 
OptionCollection.createConfiguration(context);
         ReportConfigurationTest.validateDefault(config);
     }
diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java 
b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java
index c0f2da00..306fb809 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java
@@ -23,16 +23,23 @@ import static org.assertj.core.api.Fail.fail;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.IOException;
 import java.io.PrintStream;
+import java.lang.reflect.Method;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
 
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.TreeMap;
+import java.util.UUID;
+import java.util.regex.Pattern;
 import javax.xml.XMLConstants;
 import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
@@ -45,9 +52,6 @@ import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathFactory;
 
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.ParseException;
 import org.apache.commons.io.FileUtils;
 import org.apache.rat.api.Document.Type;
 import org.apache.rat.api.RatException;
@@ -58,12 +62,16 @@ import org.apache.rat.license.ILicenseFamily;
 import org.apache.rat.report.claim.ClaimStatistic;
 import org.apache.rat.report.claim.ClaimStatisticTest;
 import org.apache.rat.test.utils.Resources;
-import org.apache.rat.testhelpers.TextUtils;
+import org.apache.rat.testhelpers.BaseOption;
+import org.apache.rat.testhelpers.BaseOptionCollection;
 import org.apache.rat.testhelpers.XmlUtils;
 import org.apache.rat.utils.StandardXmlFactory;
 import org.apache.rat.walker.DirectoryWalker;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.api.TestInfo;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
@@ -72,22 +80,60 @@ import org.xml.sax.SAXException;
  * Tests the output of the Reporter.
  */
 public class ReporterTest {
-    @TempDir
-    File tempDirectory;
+    /**
+     * temporary file.  Not using tempDir because it does not
+     * always work.
+     */
+    private static Path tempPath;
+
+    /**
+     * The directory for the test.
+     */
+    private Path testPath;
+
+    /**
+     * Directory for the test data.
+     */
     final String basedir;
 
+    private final OptionCollectionParser<BaseOption> collectionParser;
+
     ReporterTest() throws URISyntaxException {
         basedir = Resources.getExampleResource("exampleData").getPath();
+        collectionParser = new OptionCollectionParser<>(new 
BaseOptionCollection());
     }
 
-    @Test
-    void testExecute() throws RatException, ParseException {
-        File output = new File(tempDirectory, "testExecute");
+    @BeforeAll
+    static void setUp() throws IOException {
+        tempPath = Files.createTempDirectory("ReporterTest");
+    }
 
-        CommandLine cl = new 
DefaultParser().parse(OptionCollection.buildOptions(), new 
String[]{"--output-style", "xml", "--output-file", output.getPath(), basedir});
-        ArgumentContext context = new ArgumentContext(new File("."), cl);
-        ReportConfiguration config = 
OptionCollection.createConfiguration(context);
-        ClaimStatistic statistic = new 
Reporter(config).execute().getStatistic();
+    @AfterAll
+    static void cleanup() throws IOException {
+        FileUtils.deleteDirectory(tempPath.toFile());
+    }
+
+    @BeforeEach
+    void setUpTest(TestInfo testInfo) {
+        Optional<Method> testMethod = testInfo.getTestMethod();
+        this.testPath = 
tempPath.resolve(testMethod.map(Method::getName).orElseGet(() -> 
UUID.randomUUID().toString()));
+        File file = testPath.toFile();
+        if (!file.exists()) {
+            if (!file.mkdirs()) {
+                throw new RuntimeException("Unable to create temp directory: " 
+ file.getName());
+            }
+        } else {
+            if (!file.isDirectory()) {
+                throw new RuntimeException(file.getName() + " is NOT a 
directory.");
+            }
+        }
+    }
+
+    @Test
+    void testExecute() throws RatException {
+        File output = testPath.resolve("output.xml").toFile();
+        ArgumentContext ctxt = collectionParser.parseCommands(new File("."), 
new String[]{"--output-style", "xml", "--output-file", output.getPath(), 
basedir});
+        ClaimStatistic statistic = new 
Reporter(ctxt.getConfiguration()).execute().getStatistic();
 
         assertThat(statistic.getCounter(Type.ARCHIVE)).isEqualTo(1);
         assertThat(statistic.getCounter(Type.BINARY)).isEqualTo(2);
@@ -136,11 +182,9 @@ public class ReporterTest {
     }
 
     @Test
-    void testExecuteNoSource() throws ParseException, RatException, 
TransformerException {
-        File output = new File(tempDirectory, "testExecuteNoSource");
-
-        CommandLine cl = new 
DefaultParser().parse(OptionCollection.buildOptions(), new 
String[]{"--output-style", "xml", "--output-file", output.getPath()});
-        ArgumentContext context = new ArgumentContext(new File("."), cl);
+    void testExecuteNoSource() throws RatException, TransformerException {
+        File output = testPath.resolve("testExecuteNoSource").toFile();
+        ArgumentContext context = collectionParser.parseCommands(new 
File("."), new String[]{"--output-style", "xml", "--output-file", 
output.getPath()});
         ReportConfiguration config = 
OptionCollection.createConfiguration(context);
         Reporter.Output result = new Reporter(config).execute();
         
assertThat(StandardXmlFactory.serializeDocument(result.getDocument())).isEmpty();
@@ -149,43 +193,34 @@ public class ReporterTest {
 
     @Test
     void testOutputOption() throws Exception {
-        File output = new File(tempDirectory, "test");
-        CommandLine commandLine = new 
DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"-o", 
output.getCanonicalPath(), basedir});
-        ArgumentContext context = new ArgumentContext(new File("."), 
commandLine);
-
-        ReportConfiguration config = 
OptionCollection.createConfiguration(context);
-        new Reporter(config).execute().format(config);
+        File output = testPath.resolve("testOutputOption.txt").toFile();
+        ArgumentContext ctxt = collectionParser.parseCommands(new File("."), 
new String[]{"--output-file", output.getCanonicalPath(), basedir});
+        new 
Reporter(ctxt.getConfiguration()).execute().format(ctxt.getConfiguration());
         assertThat(output.exists()).isTrue();
         String content = FileUtils.readFileToString(output, 
StandardCharsets.UTF_8);
-        TextUtils.assertPatternInTarget("^! Unapproved:\\s*2 ", content);
-        assertThat(content).contains("/Source.java");
-        assertThat(content).contains("/sub/Empty.txt");
+        assertThat(content).containsPattern(Pattern.compile("^! 
Unapproved:\\s*2 ", Pattern.MULTILINE))
+                .contains("/Source.java")
+                .contains("/sub/Empty.txt");
     }
 
     @Test
     void testGetOutputMethod() throws Exception {
-        File output = new File(tempDirectory, "test");
-        CommandLine commandLine = new 
DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"-o", 
output.getCanonicalPath(), basedir});
-        ArgumentContext context = new ArgumentContext(new File("."), 
commandLine);
-
-        ReportConfiguration config = 
OptionCollection.createConfiguration(context);
-        Reporter reporter = new Reporter(config);
+        File output = testPath.resolve("testGetOutputMethod.txt").toFile();
+        ArgumentContext context = collectionParser.parseCommands(new 
File("."), new String[]{"-o", output.getCanonicalPath(), basedir});
+        Reporter reporter = new Reporter(context.getConfiguration());
         Reporter.Output expected = reporter.execute();
         assertThat(reporter.getOutput()).isEqualTo(expected);
     }
 
     @Test
     void testDefaultOutput() throws Exception {
-        File output = new File(tempDirectory, "testDefaultOutput");
+        File output = testPath.resolve("captured.txt").toFile();
 
         PrintStream origin = System.out;
         try (PrintStream out = new PrintStream(output)) {
             System.setOut(out);
-            CommandLine commandLine = new 
DefaultParser().parse(OptionCollection.buildOptions(), new String[]{basedir});
-            ArgumentContext context = new ArgumentContext(new File("."), 
commandLine);
-
-            ReportConfiguration config = 
OptionCollection.createConfiguration(context);
-            new Reporter(config).execute().format(config);
+            ArgumentContext ctxt = collectionParser.parseCommands(new 
File("."), new String[]{basedir});
+            new 
Reporter(ctxt.getConfiguration()).execute().format(ctxt.getConfiguration());
         } finally {
             System.setOut(origin);
         }
@@ -233,13 +268,10 @@ public class ReporterTest {
         expected.put("/tri.txt", mapOf("encoding", "ISO-8859-1", "mediaType", 
"text/plain",
                 "type", "STANDARD"));
 
-        File output = new File(tempDirectory, ".rat/testXMLOutput");
-        output.getParentFile().mkdir();
-        CommandLine commandLine = new 
DefaultParser().parse(OptionCollection.buildOptions(), new 
String[]{"--output-style", "xml", "--output-file", output.getPath(), basedir});
-        ArgumentContext context = new ArgumentContext(tempDirectory, 
commandLine);
-
-        ReportConfiguration config = 
OptionCollection.createConfiguration(context);
-        new Reporter(config).execute().format(config);
+        File output = testPath.resolve(".rat/testXMLOutput").toFile();
+        output.getParentFile().mkdirs();
+        ArgumentContext ctxt = 
collectionParser.parseCommands(testPath.toFile(), new 
String[]{"--output-style", "xml", "--output-file", output.getPath(), basedir});
+        new 
Reporter(ctxt.getConfiguration()).execute().format(ctxt.getConfiguration());
 
         assertThat(output).exists();
         Document doc = 
XmlUtils.toDom(java.nio.file.Files.newInputStream(output.toPath()));
@@ -368,56 +400,49 @@ public class ReporterTest {
     }
 
     private void verifyStandardContent(final String document) {
-        TextUtils.assertPatternInTarget("^  Notices:\\s*2 ", document);
-        TextUtils.assertPatternInTarget("^  Binaries:\\s*2 ", document);
-        TextUtils.assertPatternInTarget("^  Archives:\\s*1 ", document);
-        TextUtils.assertPatternInTarget("^  Standards:\\s*8 ", document);
-        TextUtils.assertPatternInTarget("^  Ignored:\\s*2 ", document);
-        TextUtils.assertPatternInTarget("^! Unapproved:\\s*2 ", document);
-        TextUtils.assertPatternInTarget("^  Unknown:\\s*2 ", document);
-
-        TextUtils.assertPatternInTarget("^Apache License 2.0: 5 ", document);
-        TextUtils.assertPatternInTarget("^BSD 3 clause: 1 ", document);
-        TextUtils.assertPatternInTarget("^The MIT License: 1 ", document);
-        TextUtils.assertPatternInTarget("^The Telemanagement Forum License: 1 
", document);
-        TextUtils.assertPatternInTarget("^Unknown license: 2 ", document);
-
-        TextUtils.assertPatternInTarget("^\\Q?????\\E: 2 ", document);
-        TextUtils.assertPatternInTarget("^AL   : 5 ", document);
-        TextUtils.assertPatternInTarget("^BSD-3: 2 ", document);
-        TextUtils.assertPatternInTarget("^MIT  : 1 ", document);
-
-        TextUtils.assertPatternInTarget(
-                "^Files with unapproved licenses\\s+\\*+\\s+" //
+        assertThat(document)
+                .containsPattern(Pattern.compile("^  Notices:\\s*2 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^  Binaries:\\s*2 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^  Archives:\\s*1 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^  Standards:\\s*8 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^  Ignored:\\s*2 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^! Unapproved:\\s*2 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^  Unknown:\\s*2 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^Apache License 2.0: 5 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^BSD 3 clause: 1 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^The MIT License: 1 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^The Telemanagement Forum 
License: 1 ", Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^Unknown license: 2 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^\\Q?????\\E: 2 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^AL   : 5 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^BSD-3: 2 ", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("^MIT  : 1 ", 
Pattern.MULTILINE))
+                .containsPattern(
+                        Pattern.compile("^Files with unapproved 
licenses\\s+\\*+\\s+" //
                         + "\\Q/Source.java\\E\\s+" //
-                        + "\\Q/sub/Empty.txt\\E\\s",
-                document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.ARCHIVE, "/dummy.jar"),
-                document);
-        TextUtils.assertPatternInTarget(
-                ReporterTestUtils.documentOut(true, Type.STANDARD, 
"/ILoggerFactory.java")
-                        + ReporterTestUtils.licenseOut("MIT", "The MIT 
License"),
-                document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.BINARY, "/Image.png"),
-                document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.NOTICE, "/LICENSE"),
-                document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.NOTICE, "/NOTICE"), document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(false, 
Type.STANDARD, "/Source.java")
-                + ReporterTestUtils.UNKNOWN_LICENSE, document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/Text.txt")
-                + ReporterTestUtils.APACHE_LICENSE, document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/Xml.xml")
-                + ReporterTestUtils.APACHE_LICENSE, document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/buildr.rb")
-                + ReporterTestUtils.APACHE_LICENSE, document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/TextHttps.txt")
-                + ReporterTestUtils.APACHE_LICENSE, document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/tri.txt")
+                                + "\\Q/sub/Empty.txt\\E\\s", 
Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.ARCHIVE, "/dummy.jar"), Pattern.MULTILINE))
+                .containsPattern(
+                        Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/ILoggerFactory.java")
+                                + ReporterTestUtils.licenseOut("MIT", "The MIT 
License"), Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.BINARY, "/Image.png"), Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.NOTICE, "/LICENSE"), Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.NOTICE, "/NOTICE"), Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(false, 
Type.STANDARD, "/Source.java")
+                        + ReporterTestUtils.UNKNOWN_LICENSE, 
Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/Text.txt")
+                        + ReporterTestUtils.APACHE_LICENSE, Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/Xml.xml")
+                        + ReporterTestUtils.APACHE_LICENSE, Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/buildr.rb")
+                        + ReporterTestUtils.APACHE_LICENSE, Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/TextHttps.txt")
+                        + ReporterTestUtils.APACHE_LICENSE, Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(true, 
Type.STANDARD, "/tri.txt")
                 + ReporterTestUtils.APACHE_LICENSE + 
ReporterTestUtils.licenseOut("BSD-3", "BSD 3 clause")
-                + ReporterTestUtils.licenseOut("BSD-3", "TMF", "The 
Telemanagement Forum License"), document);
-        TextUtils.assertPatternInTarget(ReporterTestUtils.documentOut(false, 
Type.STANDARD, "/sub/Empty.txt")
-                + ReporterTestUtils.UNKNOWN_LICENSE, document);
+                        + ReporterTestUtils.licenseOut("BSD-3", "TMF", "The 
Telemanagement Forum License"), Pattern.MULTILINE))
+                
.containsPattern(Pattern.compile(ReporterTestUtils.documentOut(false, 
Type.STANDARD, "/sub/Empty.txt")
+                        + ReporterTestUtils.UNKNOWN_LICENSE, 
Pattern.MULTILINE));
     }
 
     private Validator initValidator() throws SAXException {
@@ -481,8 +506,9 @@ public class ReporterTest {
 
         String document = out.toString();
 
-        TextUtils.assertNotContains("<?xml version=\"1.0\" 
encoding=\"UTF-8\"?>", document);
-        assertThat(document).as(() -> "'Generated at' is not present in \n" + 
document).startsWith(HEADER);
+        assertThat(document).as(() -> "'Generated at' is not present in \n" + 
document)
+                .doesNotContainPattern("<?xml version=\"1.0\" 
encoding=\"UTF-8\"?>")
+                .startsWith(HEADER);
 
         verifyStandardContent(document);
     }
@@ -497,9 +523,9 @@ public class ReporterTest {
 
         String document = out.toString();
 
-        TextUtils.assertContains("Generated at: ", document );
-        TextUtils.assertPatternInTarget("\\Q/Source.java\\E$", document);
-        TextUtils.assertPatternInTarget("\\Q/sub/Empty.txt\\E", document);
+        assertThat(document).containsOnlyOnce("Generated at: ")
+                .containsPattern(Pattern.compile("\\Q/Source.java\\E$", 
Pattern.MULTILINE))
+                .containsPattern(Pattern.compile("\\Q/sub/Empty.txt\\E", 
Pattern.MULTILINE));
     }
 
     @Test
diff --git 
a/apache-rat-core/src/test/java/org/apache/rat/commandline/ArgTests.java 
b/apache-rat-core/src/test/java/org/apache/rat/commandline/ArgTests.java
index 742632c5..873d47c5 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/commandline/ArgTests.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/commandline/ArgTests.java
@@ -18,13 +18,8 @@
  */
 package org.apache.rat.commandline;
 
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.rat.CLIOptionCollection;
-import org.apache.rat.DeprecationReporter;
-import org.apache.rat.OptionCollection;
 import org.apache.rat.ReportConfiguration;
 import org.apache.rat.document.DocumentName;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -35,17 +30,12 @@ import java.nio.file.Path;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-public class ArgTests {
-
-    private CommandLine createCommandLine(String[] args) throws ParseException 
{
-        Options opts = OptionCollection.buildOptions();
-        return 
DefaultParser.builder().setDeprecatedHandler(DeprecationReporter.getLogReporter())
-                .setAllowPartialMatching(true).build().parse(opts, args);
-    }
+class ArgTests {
+    final private CLIOptionCollection cliOptionCollection = new 
CLIOptionCollection();
 
     @ParameterizedTest(name = "{0}")
     @ValueSource(strings = { "rat.txt", "./rat.txt", "/rat.txt", 
"target/rat.test" })
-    public void outputFileNameNoDirectoryTest(String name) throws 
ParseException {
+    void outputFileNameNoDirectoryTest(String name) throws ParseException {
         class OutputFileConfig extends ReportConfiguration {
             private File actual = null;
 
@@ -62,10 +52,9 @@ public class ArgTests {
         Path workingPath = localFile.getAbsoluteFile().toPath();
         String expected = fsInfo.normalize(workingPath.resolve("./" + 
fileName).toString());
 
-        CommandLine commandLine = createCommandLine(new 
String[]{"--output-file", fileName});
         OutputFileConfig configuration = new OutputFileConfig();
-        ArgumentContext ctxt = new ArgumentContext(localFile, configuration, 
commandLine);
-        Arg.processArgs(ctxt, CLIOptionCollection.INSTANCE);
+        ArgumentContext ctxt = new ArgumentContext(localFile, configuration, 
cliOptionCollection.getOptions(), new String[]{"--output-file", fileName});
+        Arg.processArgs(ctxt, cliOptionCollection);
         if (name.equals("/rat.txt")) {
             
assertThat(fsInfo.normalize(configuration.actual.getAbsolutePath())).isEqualTo(localFileName.getRoot()
 + "rat.txt");
         } else {
diff --git 
a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOption.java 
b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOption.java
new file mode 100644
index 00000000..1a7faff2
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOption.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   https://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ */
+package org.apache.rat.testhelpers;
+
+import org.apache.commons.cli.Option;
+import org.apache.rat.ui.ArgumentTracker;
+import org.apache.rat.ui.UIOption;
+import org.apache.rat.utils.CasedString;
+
+import java.util.function.Function;
+
+public final class BaseOption extends UIOption<BaseOption> {
+    BaseOption(BaseOptionBuilder builder) {
+        super(builder);
+    }
+
+    public Builder builder() {
+        return new BaseOptionBuilder();
+    }
+
+    protected String cleanupName(Option option) {
+        return ArgumentTracker.extractKey(option);
+    }
+
+    public String getExample() {
+        return "";
+    }
+
+    public String getText() {
+        return "";
+    }
+
+    public static class BaseOptionBuilder extends UIOption.Builder<BaseOption, 
BaseOptionBuilder> {
+
+        @Override
+        protected Function<Option, CasedString> getNameFactory() {
+            return ArgumentTracker::extractName;
+        }
+
+        @Override
+        protected BaseOption doBuild() {
+            return new BaseOption(this);
+        }
+    }
+}
diff --git 
a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOptionCollection.java
 
b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOptionCollection.java
new file mode 100644
index 00000000..262ae733
--- /dev/null
+++ 
b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOptionCollection.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   https://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ */
+package org.apache.rat.testhelpers;
+
+import org.apache.rat.ui.UIOptionCollection;
+
+public final class BaseOptionCollection extends UIOptionCollection<BaseOption> 
{
+    public BaseOptionCollection() {
+        super(new Builder());
+    }
+
+    public BaseOptionCollection(Builder builder) {
+        super(builder);
+    }
+    public static final class Builder extends 
UIOptionCollection.Builder<BaseOption, Builder> {
+        public Builder() {
+            super(BaseOption.BaseOptionBuilder::new);
+        }
+    }
+}
diff --git 
a/apache-rat-core/src/test/java/org/apache/rat/ui/ArgumentTrackerTest.java 
b/apache-rat-core/src/test/java/org/apache/rat/ui/ArgumentTrackerTest.java
index 74fd2810..4c269c03 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/ui/ArgumentTrackerTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/ui/ArgumentTrackerTest.java
@@ -113,7 +113,7 @@ class ArgumentTrackerTest {
     @Test
     void invalidAbstractOption() {
         Option option = Option.builder().longOpt("notAValidOption").build();
-        TestingUIOption invalidOption = new 
TestingUIOption(testingUIOptionCollection, option);
+        TestingUIOption invalidOption = new 
TestingUIOption.TestingUIOptionBuilder().option(option).optionCollection(testingUIOptionCollection).build();
         underTest.addArg(invalidOption, "foo");
         assertThat(underTest.getArg(invalidOption.keyValue())).isEmpty();
     }
diff --git 
a/apache-rat-core/src/test/java/org/apache/rat/ui/UIOptionCollectionTest.java 
b/apache-rat-core/src/test/java/org/apache/rat/ui/UIOptionCollectionTest.java
index b1a4e6b7..5b1c4861 100644
--- 
a/apache-rat-core/src/test/java/org/apache/rat/ui/UIOptionCollectionTest.java
+++ 
b/apache-rat-core/src/test/java/org/apache/rat/ui/UIOptionCollectionTest.java
@@ -21,6 +21,8 @@ package org.apache.rat.ui;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
+import java.util.function.Function;
+
 import org.apache.commons.cli.AlreadySelectedException;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionGroup;
@@ -41,9 +43,10 @@ public class UIOptionCollectionTest {
             super(new Builder());
 
         }
+
         private static class Builder extends 
UIOptionCollection.Builder<TestingUIOption, Builder> {
             Builder() {
-                super(TestingUIOption::new);
+                super(TestingUIOption.TestingUIOptionBuilder::new);
                         uiOption(UI_OPTION)
                         .uiOption(DEPRECATED_UI_OPTION)
                         .unsupported(Arg.COUNTER_MAX)
@@ -54,10 +57,10 @@ public class UIOptionCollectionTest {
         }
     }
 
-    static class TestingUIOption extends UIOption<TestingUIOption> {
+    public static class TestingUIOption extends UIOption<TestingUIOption> {
 
-        TestingUIOption(final UIOptionCollection<TestingUIOption> collection, 
final Option option) {
-            super(collection, option, 
ArgumentTracker.extractName(option).as(CasedString.StringCase.DOT));
+        private TestingUIOption(final TestingUIOptionBuilder builder) {
+            super(builder);
         }
 
         @Override
@@ -74,6 +77,19 @@ public class UIOptionCollectionTest {
         public String getText() {
             return "Short and long options for " + cleanupName(option);
         }
+
+        public static class TestingUIOptionBuilder extends 
UIOption.Builder<TestingUIOption, TestingUIOptionBuilder> {
+
+            @Override
+            protected Function<Option, CasedString> getNameFactory() {
+                return o -> 
ArgumentTracker.extractName(option()).as(CasedString.StringCase.DOT);
+            }
+
+            @Override
+            protected TestingUIOption doBuild() {
+                return new TestingUIOption(this);
+            }
+        }
     }
 
     private final TestingUIOptionCollection underTest = new 
TestingUIOptionCollection();
diff --git a/apache-rat-core/src/test/java/org/apache/rat/ui/UIOptionTest.java 
b/apache-rat-core/src/test/java/org/apache/rat/ui/UIOptionTest.java
index 2b59fa7a..0c8759ac 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/ui/UIOptionTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/ui/UIOptionTest.java
@@ -30,7 +30,8 @@ class UIOptionTest {
     @Test
     void cleanup() {
         optionCollection = new 
UIOptionCollectionTest.TestingUIOptionCollection();
-        underTest = new 
UIOptionCollectionTest.TestingUIOption(optionCollection, new Option("a", false, 
"An option"));
+        underTest = new 
UIOptionCollectionTest.TestingUIOption.TestingUIOptionBuilder().option(new 
Option("a", false, "An option"))
+                .optionCollection(optionCollection).build();
         String s = underTest.cleanup("The name is --output-licenses because I 
said so");
         assertThat(s).isEqualTo("The name is output.licenses because I said 
so");
 
diff --git a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Help.java 
b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Help.java
index 56e08e1b..7979ef2d 100644
--- a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Help.java
+++ b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Help.java
@@ -179,7 +179,7 @@ public class Help extends BaseAntTask {
             int max = optionTitle.length();
             int maxExample = exampleTitle.length();
             final List<AntOption> optList = new ArrayList<>();
-            
AntOptionCollection.INSTANCE.getMappedOptions().forEach(optList::add);
+            new AntOptionCollection().getMappedOptions().forEach(optList::add);
             optList.sort(Comparator.comparing(UIOption::getName));
             List<String> exampleList = new ArrayList<>();
             for (final AntOption option : optList) {
diff --git 
a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/GeneratedReportTest.java
 
b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/GeneratedReportTest.java
index 0f590cba..8e5cf981 100644
--- 
a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/GeneratedReportTest.java
+++ 
b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/GeneratedReportTest.java
@@ -185,7 +185,7 @@ public class GeneratedReportTest {
      */
     static Stream<Arguments> generatedData() {
 
-        List<AntOption> options = 
AntOptionCollection.INSTANCE.getMappedOptions().toList();
+        List<AntOption> options = new 
AntOptionCollection().getMappedOptions().toList();
 
         List<Arguments> lst = new ArrayList<>();
 
@@ -228,11 +228,7 @@ public class GeneratedReportTest {
             if (body == null) {
                 xml.append(format("      <%1$s>%2$s</%1$s>%n", 
actualOption.getName(), getData(option)));
             } else {
-//                if (actualOption.argCount() == 1) {
-//                    xml.append(format("      <%s %s=\"%s\" />%n", 
actualOption.getName(), createAttribute(option), getData(option)));
-//                } else {
                 xml.append(format("      <%1$s>%2$s</%1$s>%n", 
actualOption.getName(), body));
-//                }
             }
         }
 
diff --git 
a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java 
b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
index ea2172a6..b3cdc4e2 100644
--- 
a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
+++ 
b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
@@ -96,6 +96,7 @@ public class ReportOptionTest  {
     }
 
     final static class AntOptionsProvider extends 
AbstractConfigurationOptionsProvider implements ArgumentsProvider {
+        private AntOptionCollection antOptionCollection = new 
AntOptionCollection();
 
         public AntOptionsProvider() {
             super(BaseAntTask.unsupportedArgs(), testPath.toFile());
@@ -138,7 +139,7 @@ public class ReportOptionTest  {
             final String name;
 
             BuildTask(Option option) {
-                
this(AntOptionCollection.INSTANCE.getMappedOption(option).get().getName());
+                
this(antOptionCollection.getMappedOption(option).get().getName());
             }
 
             BuildTask() {
@@ -154,7 +155,7 @@ public class ReportOptionTest  {
                 Map<String, String> attributes = new HashMap<>();
                 if (args.get(0).getKey() != null) {
                     for (Pair<Option, String[]> pair : args) {
-                        AntOption argOption = 
AntOptionCollection.INSTANCE.getMappedOption(pair.getKey()).get();
+                        AntOption argOption = 
antOptionCollection.getMappedOption(pair.getKey()).get();
                         if (argOption.isAttribute()) {
                             String value = pair.getValue() == null ? "true" : 
pair.getValue()[0];
                             attributes.put(argOption.getName(), value);
diff --git 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOption.java
 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOption.java
index e3cdc580..7d27bbf6 100644
--- 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOption.java
+++ 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOption.java
@@ -22,25 +22,27 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Function;
 
 import org.apache.commons.cli.Option;
 import org.apache.rat.ui.UIOption;
 import org.apache.rat.ui.UIOptionCollection;
+import org.apache.rat.utils.CasedString;
 
 import static java.lang.String.format;
 
 /**
  * A class that wraps the CLI option and provides Ant specific values.
  */
-public class AntOption extends UIOption<AntOption> {
+public final class AntOption extends UIOption<AntOption> {
 
     /**
      * Constructor.
      *
-     * @param option the option to wrap.
+     * @param builder the AntOptionBuilder
      */
-    public AntOption(final UIOptionCollection<AntOption> collection, final 
Option option) {
-        super(collection, option, AntOptionCollection.createName(option));
+    private AntOption(final AntOptionBuilder builder) {
+        super(builder);
     }
 
     /**
@@ -76,7 +78,8 @@ public class AntOption extends UIOption<AntOption> {
     }
 
     /**
-     * Gets the set of options that are mapped to this option.
+     * Gets the set of options that are mapped to this option.  This is used 
to allow one implementation to answer for
+     * multiple options.
      * @return the set of options that are mapped to this option.
      */
     public Set<AntOption> convertedFrom() {
@@ -104,15 +107,28 @@ public class AntOption extends UIOption<AntOption> {
         return antOption.cleanupName();
     }
 
+    /**
+     * Cleans up the name of this AntOption.  Used in documentation.
+     * Returns either {@code <name>} or {@code name attribute}.
+     * @return the cleaned up name.
+     */
     public String cleanupName() {
         String fmt = isAttribute() ? "%s attribute" : "<%s>";
         return format(fmt, name);
     }
 
+    /**
+     * Gets the AntOptionCollection this AntOption is associated with.
+     * @return the AntOptionCollection this AntOption is associated with.
+     */
     AntOptionCollection getAntCollection() {
         return getOptionCollection();
     }
 
+    /**
+     * Gets the Ant build type for this option.
+     * @return the Ant build type for this option.
+     */
     public AntOptionCollection.BuildType buildType() {
         return getAntCollection().buildType(this.getArgType());
     }
@@ -194,4 +210,54 @@ public class AntOption extends UIOption<AntOption> {
             return result.toString();
         }
     }
+
+    /**
+     * The Builder for AntOptions.
+     */
+    public static class AntOptionBuilder extends UIOption.Builder<AntOption, 
AntOptionBuilder> {
+
+        public AntOptionBuilder() {
+        }
+
+        /**
+         * returns the function to convert an Option to its Ant based cased 
name.
+         * @return the function to convert an Option to its Ant based cased 
name.
+         */
+        protected Function<Option, CasedString> getNameFactory() {
+            return this::createName;
+        }
+
+        @Override
+        public AntOptionBuilder optionCollection(final 
UIOptionCollection<AntOption> optionCollection) {
+            if (optionCollection instanceof AntOptionCollection) {
+                return super.optionCollection(optionCollection);
+            }
+            throw new IllegalArgumentException("Option collection must be 
instance of AntOptionCollection");
+        }
+
+        @Override
+        protected AntOption doBuild() {
+            return new AntOption(this);
+        }
+
+        /**
+         * Creates the name for the option based on rules for conversion of 
Option names.
+         * Ant names are in PASCAL format.
+         * @param option the standard option.
+         * @return a new CasedString comprising the name of the AntOption.
+         * @see CasedString.StringCase#PASCAL
+         */
+        CasedString createName(final Option option) {
+            List<String> pluralEndings = List.of("approved", "denied");
+            String name = optionCollection().rename(option);
+            CasedString casedName = new 
CasedString(CasedString.StringCase.KEBAB, name);
+            String[] segments = casedName.getSegments();
+            String lastSegment = segments[segments.length - 1];
+            if (option.hasArgs() && !lastSegment.endsWith("s") && 
!pluralEndings.contains(lastSegment)) {
+                segments[segments.length - 1] += "s";
+                casedName = new CasedString(CasedString.StringCase.KEBAB, 
segments);
+            }
+            return casedName.as(CasedString.StringCase.PASCAL);
+        }
+    }
 }
diff --git 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOptionCollection.java
 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOptionCollection.java
index 88f38c0c..b429d615 100644
--- 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOptionCollection.java
+++ 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOptionCollection.java
@@ -35,30 +35,24 @@ import org.apache.commons.text.WordUtils;
 import org.apache.rat.OptionCollection;
 import org.apache.rat.commandline.Arg;
 import org.apache.rat.document.DocumentName;
-import org.apache.rat.ui.ArgumentTracker;
 import org.apache.rat.ui.UIOptionCollection;
-import org.apache.rat.utils.CasedString;
 
 import static java.lang.String.format;
 
 /**
- * The collection of AntOptions equivalent to the CLI options
- * with any unsupported options removed.
+ * The collection of AntOptions.
  */
 public final class AntOptionCollection extends UIOptionCollection<AntOption> {
     /** mapping of standard name to non-conflicting name. */
-    private static final Map<String, String> RENAME_MAP;
-
+    static final Map<String, String> RENAME_MAP;
     /**
      * The format for an XML element.
      */
     private static final String DEFAULT_XML = "<%1$s>%%s</%1$s>%n";
-
     /** Attributes that are required for example data. */
     private static final Map<String, Map<String, String>> REQUIRED_ATTRIBUTES 
= new HashMap<>();
     /** The list of data types that are specified as XML attributes in Ant 
build.xml documents */
     private static final List<Class<?>> ATTRIBUTE_TYPES = new ArrayList<>();
-
     /** The map of option name conversions. */
     private final Map<Option, Option> conversionMap;
 
@@ -82,21 +76,38 @@ public final class AntOptionCollection extends 
UIOptionCollection<AntOption> {
         ATTRIBUTE_TYPES.add(DocumentName.class);
     }
 
+    /**
+     * Gets the map of standard Option names that are renamed to fit the Ant 
naming process.
+     * @return the map of renamed Options.
+     */
     public static Map<String, String> getRenameMap() {
         return new TreeMap<>(RENAME_MAP);
     }
 
-    /** The instance of the AntOptionCollection */
-    public static final AntOptionCollection INSTANCE = new Builder().build();
-
+    /** Creates an instance of the AntOption Collection.
+     */
+    public AntOptionCollection() {
+        this(new Builder());
+    }
     /**
      * Create an instance.
      */
     private AntOptionCollection(final Builder builder) {
-        super(builder);
+        super(new Builder());
         conversionMap = builder.conversions;
     }
 
+    @Override
+    public String rename(final Option option) {
+        String key = super.rename(option);
+        return StringUtils.defaultIfEmpty(RENAME_MAP.get(key), key);
+    }
+
+    /**
+     * Returns the set of Antoptions that the argument was converted From.
+     * @param antOption the AntOption to check.
+     * @return returns a Set of AntOptoins that were converted to the 
argument. May be an empty set.
+     */
     public Set<AntOption> convertedFrom(final AntOption antOption) {
         return conversionMap.entrySet().stream().filter(e -> 
e.getValue().equals(antOption.getOption()))
                 .map(e -> getMappedOption(e.getKey()))
@@ -115,16 +126,31 @@ public final class AntOptionCollection extends 
UIOptionCollection<AntOption> {
         return opt == null ? antOption : 
getMappedOption(opt).orElse(antOption);
     }
 
+    /**
+     * Returns {@code true} if this argument is an attribute to the ANT RAT 
call.
+     * @param antOption the AntOption to check.
+     * @return {@code true} if this argument is an attribute to the ANT RAT 
call.
+     */
     public boolean isAttribute(final AntOption antOption) {
         Option opt = antOption.getOption();
         return (!opt.hasArg() || opt.getArgs() == 1) && 
convertedFrom(antOption).isEmpty() &&
                 ATTRIBUTE_TYPES.contains(opt.getType());
     }
 
+    /**
+     * Gets a map of attributes that are required for the example data.
+     * @param name the attribute name to lookup.
+     * @return the map of attributes that are required for the example data.
+     */
     public Map<String, String> getRequiredAttributes(final String name) {
         return REQUIRED_ATTRIBUTES.get(name);
     }
 
+    /**
+     * Gets the ANT build type for the ArgumentType
+     * @param type ArgumentType to get the ANT build type for.
+     * @return the ANT build type for the ArgumentType
+     */
     BuildType buildType(final OptionCollection.ArgumentType type) {
         return switch (type) {
             case FILE, DIRORARCHIVE -> new BuildType("filename") {
@@ -147,37 +173,6 @@ public final class AntOptionCollection extends 
UIOptionCollection<AntOption> {
         };
     }
 
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    /**
-     * Provides a new name for an option if it is renamed in the collection.
-     * @param name the option name.
-     * @return the collection name, may be the same as the option name.
-     */
-    static String rename(final String name) {
-        return StringUtils.defaultIfEmpty(RENAME_MAP.get(name), name);
-    }
-
-    /**
-     * Creates the name for the option based on rules for conversion of CLI 
option names.
-     * @param option the standard option.
-     * @return the new Option name as a CasedString.
-     */
-    static CasedString createName(final Option option) {
-        List<String> pluralEndings = List.of("approved", "denied");
-        String name = rename(ArgumentTracker.extractKey(option));
-        CasedString casedName = new CasedString(CasedString.StringCase.KEBAB, 
name);
-        String[] segments = casedName.getSegments();
-        String lastSegment = segments[segments.length - 1];
-        if (option.hasArgs() && !lastSegment.endsWith("s") && 
!pluralEndings.contains(lastSegment)) {
-            segments[segments.length - 1] += "s";
-            casedName = new CasedString(CasedString.StringCase.KEBAB, 
segments);
-        }
-        return casedName.as(CasedString.StringCase.PASCAL);
-    }
-
     /**
      * The Builder for the AntOptionCollection.
      */
@@ -186,7 +181,7 @@ public final class AntOptionCollection extends 
UIOptionCollection<AntOption> {
         private final Map<Option, Option> conversions = new HashMap<>();
 
         private Builder() {
-            super(AntOption::new);
+            super(AntOption.AntOptionBuilder::new);
             Arg.getOptions().getOptions()
                     .stream().filter(o -> Objects.isNull(o.getLongOpt()))
                     .forEach(this::unsupported);
@@ -205,11 +200,12 @@ public final class AntOptionCollection extends 
UIOptionCollection<AntOption> {
                     .convert(Arg.EXCLUDE_STD, Arg.EXCLUDE);
         }
 
-        @Override
-        public AntOptionCollection build() {
-            return new AntOptionCollection(this);
-        }
-
+        /**
+         * Converts one Arg type to another.
+         * @param from the Arg to convert from
+         * @param to the Arg to convert to.
+         * @return this
+         */
         public Builder convert(final Arg from, final Arg to) {
             Option mapTo = to.option();
             for (Option option : from.group().getOptions()) {
@@ -269,6 +265,12 @@ public final class AntOptionCollection extends 
UIOptionCollection<AntOption> {
             return format("<%1$s>%2$s</%1$s>%n", delegateOption.getName(), 
inner);
         }
 
+        /**
+         * Gets a string comprising the Ant XML pattern for the specified 
AntOption.
+         * @param antOption the ant option to get XML example for
+         * @param data the data for the option.
+         * @return an ANT XML formatted option.
+         */
         public String getXml(final AntOption antOption, final String data) {
             AntOption delegateOption = antOption.getActualAntOption();
             if (delegateOption.isAttribute()) {
@@ -278,6 +280,11 @@ public final class AntOptionCollection extends 
UIOptionCollection<AntOption> {
             }
         }
 
+        /**
+         * Gets a test name for the AntOption.
+         * @param antOption the Ant Option being tested
+         * @return the test name for this type.
+         */
         public String testName(final AntOption antOption) {
             return addExt ? format("%s_%s", antOption.getName(), 
antOption.getArgName()) : antOption.getName();
         }
diff --git 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/MavenOption.java
 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/MavenOption.java
index 6b7397bb..cc4143a7 100644
--- 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/MavenOption.java
+++ 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/MavenOption.java
@@ -18,17 +18,19 @@
  */
 package org.apache.rat.documentation.options;
 
+import java.util.function.Function;
+
 import org.apache.commons.cli.Option;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.text.WordUtils;
+import org.apache.rat.ConfigurationException;
 import org.apache.rat.ui.UIOption;
-import org.apache.rat.ui.UIOptionCollection;
 import org.apache.rat.utils.CasedString;
 
 import static java.lang.String.format;
 
 /**
- * A representation of a Maven option based on a CLI option.
+ * A representation of a Maven option based on an Option.
  */
 public final class MavenOption extends UIOption<MavenOption> {
 
@@ -38,10 +40,10 @@ public final class MavenOption extends 
UIOption<MavenOption> {
     /**
      * Constructor.
      *
-     * @param option The CLI option
+     * @param builder The MavenOption builder.
      */
-    MavenOption(final UIOptionCollection<MavenOption> collection, final Option 
option) {
-        super(collection, option, MavenOptionCollection.createName(option));
+    private MavenOption(final MavenOptionBuilder builder) {
+        super(builder);
     }
 
     @Override
@@ -60,7 +62,8 @@ public final class MavenOption extends UIOption<MavenOption> {
     @Override
     protected String cleanupName(final Option option) {
         // only parse the option if we need to.
-        return option == this.option ? format(XML_FMT, this.name) : 
format(XML_FMT, MavenOptionCollection.createName(option));
+        return option == this.option ? format(XML_FMT, this.name) : 
format(XML_FMT,
+                
MavenOptionBuilder.createName(optionCollection.rename(option)));
     }
 
     @Override
@@ -102,29 +105,43 @@ public final class MavenOption extends 
UIOption<MavenOption> {
         return sb.toString();
     }
 
+    /**
+     * Gets the Maven Mojo method signature for this Option.
+     * @param indent the number of spaces to indent the text.
+     * @param multiple {@code true} if this option takes multiple arguments.
+     * @return the method signature for this Option.
+     */
     public String getMethodSignature(final String indent, final boolean 
multiple) {
         StringBuilder sb = new StringBuilder();
         if (isDeprecated()) {
             sb.append(format("%s@Deprecated%n", indent));
         }
-        String fname = name.toCase(CasedString.StringCase.CAMEL);
+        // the camel case name for this option.
+        String camelName = name.toCase(CasedString.StringCase.CAMEL);
+        if (camelName == null) {
+            throw new ConfigurationException("Name can not be null");
+        }
         String args = option.hasArg() ? "String" : "boolean";
         if (multiple) {
-            if (!(fname.endsWith("s") || fname.endsWith("Approved") || 
fname.endsWith("Denied"))) {
-                fname = fname + "s";
+            if (!(camelName.endsWith("s") || camelName.endsWith("Approved") || 
camelName.endsWith("Denied"))) {
+                camelName = camelName + "s";
             }
             args = args + "[]";
         }
 
         return sb.append(format("%1$s%5$s%n%1$spublic void set%3$s(%4$s %2$s)",
-                        indent, name, fname, args, 
getPropertyAnnotation(fname)))
+                        indent, name, camelName, args, 
getParameterAnnotation(camelName)))
                 .toString();
     }
 
-
-    public String getPropertyAnnotation(final String fname) {
+    /**
+     * Creates the {@code @Parameter} annotation for this option.
+     * @param camelName The camel cased name for this option.
+     * @return the string that is the parameter annotation.
+     */
+    public String getParameterAnnotation(final String camelName) {
         StringBuilder sb = new StringBuilder("@Parameter");
-        String property = option.hasArgs() ? null : format("property = 
\"rat.%s\"", fname);
+        String property = option.hasArgs() ? null : format("property = 
\"rat.%s\"", camelName);
         String defaultValue = option.isDeprecated() ? null : getDefaultValue();
         if (property != null || defaultValue != null) {
             sb.append("(");
@@ -138,4 +155,30 @@ public final class MavenOption extends 
UIOption<MavenOption> {
         }
         return sb.toString();
     }
+
+    /**
+     * The builder for the MavenOptions.
+     */
+    public static class MavenOptionBuilder extends 
UIOption.Builder<MavenOption, MavenOptionBuilder> {
+
+        @Override
+        protected Function<Option, CasedString> getNameFactory() {
+            return o -> createName(optionCollection().rename(o));
+        }
+
+        @Override
+        protected MavenOption doBuild() {
+            return new MavenOption(this);
+        }
+
+        /**
+         * Create the cased name
+         * @param key the renamed key from the collection.
+         * @return the name for the key.
+         * @see MavenOptionCollection#rename(Option)
+         */
+        static CasedString createName(final String key) {
+            return new CasedString(CasedString.StringCase.KEBAB, 
key).as(CasedString.StringCase.PASCAL);
+        }
+    }
 }
diff --git 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/MavenOptionCollection.java
 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/MavenOptionCollection.java
index 4b856ca9..8f3b5fda 100644
--- 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/MavenOptionCollection.java
+++ 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/MavenOptionCollection.java
@@ -26,9 +26,7 @@ import java.util.TreeMap;
 import org.apache.commons.cli.Option;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.rat.commandline.Arg;
-import org.apache.rat.ui.ArgumentTracker;
 import org.apache.rat.ui.UIOptionCollection;
-import org.apache.rat.utils.CasedString;
 
 /**
  * The collection of MavenOptions equivalent to the CLI options
@@ -47,10 +45,9 @@ public final class MavenOptionCollection extends 
UIOptionCollection<MavenOption>
     }
 
     /**
-     * The instance of the MavenOptionCollection.
+     * Gets the Map of renamed Options indexed by original option name.
+     * @return the map of renamed Options indexed by original option name.
      */
-    public static final MavenOptionCollection INSTANCE = new Builder().build();
-
     public static Map<String, String> getRenameMap() {
         return new TreeMap<>(RENAME_MAP);
     }
@@ -58,33 +55,14 @@ public final class MavenOptionCollection extends 
UIOptionCollection<MavenOption>
     /**
      * Create an instance.
      */
-    private MavenOptionCollection(final Builder builder) {
-        super(builder);
-    }
-
-    public static Builder builder() {
-        return new Builder();
+    public MavenOptionCollection() {
+        super(new Builder());
     }
 
-    /**
-     * Provides a new name for an option if it is renamed in the collection.
-     *
-     * @param name the option name.
-     * @return the collection name, may be the same as the option name.
-     */
-    static String rename(final String name) {
-        return StringUtils.defaultIfEmpty(RENAME_MAP.get(name), name);
-    }
-
-    /**
-     * Creates the name for the option based on rules for conversion of CLI 
option names.
-     *
-     * @param option the standard option.
-     * @return the new Option name as a CasedString.
-     */
-    static CasedString createName(final Option option) {
-        String name = rename(ArgumentTracker.extractKey(option));
-        return new CasedString(CasedString.StringCase.KEBAB, 
name).as(CasedString.StringCase.PASCAL);
+    @Override
+    public String rename(final Option option) {
+        String key = super.rename(option);
+        return StringUtils.defaultIfEmpty(RENAME_MAP.get(key), key);
     }
 
     /**
@@ -92,16 +70,11 @@ public final class MavenOptionCollection extends 
UIOptionCollection<MavenOption>
      */
     public static final class Builder extends 
UIOptionCollection.Builder<MavenOption, Builder> {
         private Builder() {
-            super(MavenOption::new);
+            super(MavenOption.MavenOptionBuilder::new);
             Arg.getOptions().getOptions()
                     .stream().filter(o -> Objects.isNull(o.getLongOpt()))
                     .forEach(this::unsupported);
             unsupported(Arg.DIR).unsupported(Arg.LOG_LEVEL);
         }
-
-        @Override
-        public MavenOptionCollection build() {
-            return new MavenOptionCollection(this);
-        }
     }
 }
diff --git 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/velocity/RatTool.java
 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/velocity/RatTool.java
index ca1adadf..7faf6ffb 100644
--- 
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/velocity/RatTool.java
+++ 
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/velocity/RatTool.java
@@ -48,6 +48,7 @@ import 
org.apache.rat.documentation.options.MavenOptionCollection;
 import org.apache.rat.help.AbstractHelp;
 import org.apache.rat.license.ILicense;
 import org.apache.rat.license.LicenseSetFactory;
+import org.apache.rat.ui.UIOption;
 import org.apache.velocity.tools.config.DefaultKey;
 import org.apache.velocity.tools.config.ValidScope;
 
@@ -86,6 +87,22 @@ public class RatTool {
     /** The license factory this tool uses. */
     private final LicenseSetFactory licenseSetFactory;
 
+    /**
+     * The Client option instance
+     */
+    // visible for testing
+    private final CLIOptionCollection cliOptions = new CLIOptionCollection();
+
+    /**
+     * The ANT option instance.
+     */
+    private final AntOptionCollection antOptions = new AntOptionCollection();
+
+    /**
+     * The Maven option instance
+     */
+    private final MavenOptionCollection mavenOptions = new 
MavenOptionCollection();
+
     /**
      * Constructor.
      */
@@ -99,8 +116,8 @@ public class RatTool {
      * @return the list of command line options.
      */
     public List<Option> options() {
-        return CLIOptionCollection.INSTANCE.getMappedOptions()
-        .map(CLIOption::getOption).toList();
+        return cliOptions.getMappedOptions()
+        .map(UIOption::getOption).toList();
     }
 
     /**
@@ -108,7 +125,7 @@ public class RatTool {
      * @return a map client option name to Ant Option.
      */
     public Map<String, AntOption> antOptions() {
-        return AntOptionCollection.INSTANCE.getOptionMap();
+        return antOptions.getOptionMap();
     }
 
     /**
@@ -116,7 +133,7 @@ public class RatTool {
      * @return a map client option name to CLI Option.
      */
     public Map<String, CLIOption> cliOptions() {
-        return CLIOptionCollection.INSTANCE.getOptionMap();
+        return cliOptions.getOptionMap();
     }
 
     /**
@@ -124,7 +141,7 @@ public class RatTool {
      * @return a map client option name to Maven Option.
      */
     public Map<String, MavenOption> mvnOptions() {
-        return MavenOptionCollection.INSTANCE.getOptionMap();
+        return mavenOptions.getOptionMap();
     }
 
     /**
diff --git 
a/apache-rat-tools/src/main/java/org/apache/rat/tools/AntDocumentation.java 
b/apache-rat-tools/src/main/java/org/apache/rat/tools/AntDocumentation.java
index 5511ab0e..eb59ae62 100644
--- a/apache-rat-tools/src/main/java/org/apache/rat/tools/AntDocumentation.java
+++ b/apache-rat-tools/src/main/java/org/apache/rat/tools/AntDocumentation.java
@@ -48,6 +48,11 @@ public final class AntDocumentation {
     /** The directory to write to. */
     private final File outputDir;
 
+    /**
+     * THe Ant Option collection instance.
+     */
+    private final AntOptionCollection antOptions = new AntOptionCollection();
+
     /**
      * Creates APT documentation files for Ant.
      * Requires 1 argument:
@@ -83,7 +88,7 @@ public final class AntDocumentation {
     }
 
     public void execute() {
-        List<AntOption> options = 
AntOptionCollection.INSTANCE.getMappedOptions().toList();
+        List<AntOption> options = antOptions.getMappedOptions().toList();
         writeAttributes(options);
         writeElements(options);
         printValueTypes();
@@ -151,7 +156,7 @@ public final class AntDocumentation {
         List<List<String>> table = new ArrayList<>();
         table.add(Arrays.asList("Value Type", "Description"));
 
-        AntOptionCollection.INSTANCE.getMappedOptions()
+        antOptions.getMappedOptions()
                 .map(antOption -> Arrays.asList(antOption.getName(), 
antOption.getDescription()))
                 .forEach(table::add);
 
diff --git 
a/apache-rat-tools/src/main/java/org/apache/rat/tools/AntGenerator.java 
b/apache-rat-tools/src/main/java/org/apache/rat/tools/AntGenerator.java
index d748dbe1..725cd876 100644
--- a/apache-rat-tools/src/main/java/org/apache/rat/tools/AntGenerator.java
+++ b/apache-rat-tools/src/main/java/org/apache/rat/tools/AntGenerator.java
@@ -124,12 +124,13 @@ public final class AntGenerator {
             System.err.println("At least three arguments are required: 
package, simple class name, target directory.");
             return;
         }
+        final AntOptionCollection antOptions = new AntOptionCollection();
 
         String packageName = args[0];
         String className = args[1];
         String destDir = args[2];
 
-        List<AntOption> options = 
AntOptionCollection.INSTANCE.getMappedOptions().toList();
+        List<AntOption> options = antOptions.getMappedOptions().toList();
 
         String pkgName = String.join(File.separator, new 
CasedString(StringCase.DOT, packageName).getSegments());
         File file = new File(new File(new File(destDir), pkgName), className + 
".java");
@@ -150,12 +151,12 @@ public final class AntGenerator {
                             writer.append(format("        
xlateName.put(\"%s\", \"%s\");%n", entry.getKey(), entry.getValue()));
                         }
 
-                        for (Option option : 
AntOptionCollection.INSTANCE.getUnsupportedOptions()
+                        for (Option option : antOptions.getUnsupportedOptions()
                                 .getOptions()) {
                             writer.append(format("        
unsupportedArgs.add(\"%s\");%n", argsKey(option)));
                         }
 
-                        for (AntOption option : 
AntOptionCollection.INSTANCE.getMappedOptions().filter(AntOption::isDeprecated).toList())
 {
+                        for (AntOption option : 
antOptions.getMappedOptions().filter(AntOption::isDeprecated).toList()) {
                             writer.append(format("        
deprecatedArgs.put(\"%s\", \"%s\");%n", argsKey(option.getOption()),
                                     format("Use of deprecated option '%s'. 
%s", option.getName(), option.getDeprecated())));
                         }
diff --git 
a/apache-rat-tools/src/main/java/org/apache/rat/tools/MavenGenerator.java 
b/apache-rat-tools/src/main/java/org/apache/rat/tools/MavenGenerator.java
index 6d12c7bf..e05cbead 100644
--- a/apache-rat-tools/src/main/java/org/apache/rat/tools/MavenGenerator.java
+++ b/apache-rat-tools/src/main/java/org/apache/rat/tools/MavenGenerator.java
@@ -74,6 +74,9 @@ public final class MavenGenerator {
         String packageName = args[0];
         String className = args[1];
         String destDir = args[2];
+
+        final MavenOptionCollection mavenOptions = new MavenOptionCollection();
+
         String pkgName = String.join(File.separator, new 
CasedString(StringCase.DOT, packageName).getSegments());
         File file = new File(new File(new File(destDir), pkgName), className + 
".java");
         System.out.println("Creating " + file);
@@ -91,16 +94,16 @@ public final class MavenGenerator {
                         for (Map.Entry<?, ?> entry : 
MavenOptionCollection.getRenameMap().entrySet()) {
                             writer.append(format("        
xlateName.put(\"%s\", \"%s\");%n", entry.getKey(), entry.getValue()));
                         }
-                        for (Option option : 
MavenOptionCollection.INSTANCE.getUnsupportedOptions().getOptions()) {
+                        for (Option option : 
mavenOptions.getUnsupportedOptions().getOptions()) {
                             writer.append(format("        
unsupportedArgs.add(\"%s\");%n", argsKey(option)));
                         }
-                        for (MavenOption option : 
MavenOptionCollection.INSTANCE.getMappedOptions().filter(MavenOption::isDeprecated).toList())
 {
+                        for (MavenOption option : 
mavenOptions.getMappedOptions().filter(MavenOption::isDeprecated).toList()) {
                             writer.append(format("        
deprecatedArgs.put(\"%s\", \"%s\");%n", argsKey(option.getOption()),
                                     format("Use of deprecated option '%s'. 
%s", option.getName(), option.getDeprecated())));
                         }
                         break;
                     case "${methods}":
-                        writeMethods(writer);
+                        writeMethods(mavenOptions, writer);
                         break;
                     case "${package}":
                         writer.append(format("package %s;%n", packageName));
@@ -162,8 +165,8 @@ public final class MavenGenerator {
         return sb.append(format("     */%n")).toString();
     }
 
-    private static void writeMethods(final FileWriter writer) throws 
IOException {
-        for (MavenOption option : 
MavenOptionCollection.INSTANCE.getMappedOptions().toList()) {
+    private static void writeMethods(final MavenOptionCollection mavenOptions, 
final FileWriter writer) throws IOException {
+        for (MavenOption option : mavenOptions.getMappedOptions().toList()) {
             writer.append(getComment(option))
                     .append(option.getMethodSignature("    ", 
option.hasArgs())).append(" {").append(System.lineSeparator())
                     .append(getBody(option))
diff --git a/apache-rat-tools/src/main/java/org/apache/rat/tools/Naming.java 
b/apache-rat-tools/src/main/java/org/apache/rat/tools/Naming.java
index acd15383..ea8b1b2a 100644
--- a/apache-rat-tools/src/main/java/org/apache/rat/tools/Naming.java
+++ b/apache-rat-tools/src/main/java/org/apache/rat/tools/Naming.java
@@ -81,10 +81,28 @@ public final class Naming {
             .addOption(INCLUDE_DEPRECATED)
             .addOption(WIDTH);
 
-    /**
-     * No instantiation of utility class.
-     */
-    private Naming() { }
+    /** The porsed command line */
+    private final CommandLine cl;
+    /** The width of the output */
+    private final int width;
+    /** The Maven options */
+    private final MavenOptionCollection mavenCollection = new 
MavenOptionCollection();
+    /** The Ant options */
+    private final AntOptionCollection antCollection = new 
AntOptionCollection();
+    /** The filter to include only non-deprecated long options */
+    private final Predicate<Option> filter;
+    /** The columns to display */
+    private final List<String> columns;
+    /** if {@code true} then show Maven options */
+    private final boolean showMaven;
+    /** if {@code true} then show Ant options */
+    private final boolean showAnt;
+    /** if {@code true} then show CLI options */
+    private final boolean addCLI;
+    /** if {@code true} then include deprecated options in output. */
+    private final boolean includeDeprecated;
+    /** The function to display the description of the option */
+    private final Function<Option, String> descriptionFunction;
 
     /**
      * Creates the CSV file.
@@ -101,43 +119,43 @@ public final class Naming {
             System.err.println("At least one argument is required: path to 
file is missing.");
             return;
         }
-        CommandLine cl = DefaultParser.builder().build().parse(OPTIONS, args);
-        int width = Math.max(cl.getParsedOptionValue(WIDTH, 
AbstractHelp.HELP_WIDTH), AbstractHelp.HELP_WIDTH);
-
-        boolean showMaven = cl.hasOption(MAVEN);
-        MavenOptionCollection mavenCollection = MavenOptionCollection.INSTANCE;
-
-        boolean showAnt = cl.hasOption(ANT);
-        AntOptionCollection antCollection = AntOptionCollection.INSTANCE;
-
-        boolean includeDeprecated = cl.hasOption(INCLUDE_DEPRECATED);
-        Predicate<Option> filter = o -> o.hasLongOpt() && (!o.isDeprecated() 
|| includeDeprecated);
+        Naming naming = new Naming(args);
+        naming.write();
+    }
+    /**
+     * No instantiation of utility class.
+     */
+    private Naming(final String[] args) throws ParseException {
+        cl = DefaultParser.builder().build().parse(OPTIONS, args);
 
-        List<String> columns = new ArrayList<>();
+        width = Math.max(cl.getParsedOptionValue(WIDTH, 
AbstractHelp.HELP_WIDTH), AbstractHelp.HELP_WIDTH);
+        showMaven = cl.hasOption(MAVEN);
+        showAnt = cl.hasOption(ANT);
+        addCLI = cl.hasOption(CLI);
+        includeDeprecated = cl.hasOption(INCLUDE_DEPRECATED);
+        filter = o -> o.hasLongOpt() && (!o.isDeprecated() || 
includeDeprecated);
 
-        if (cl.hasOption(CLI)) {
-            columns.add("CLI");
+        List<String> columnsBuilder = new ArrayList<>();
+        if (addCLI) {
+            columnsBuilder.add("CLI");
         }
-
         if (showAnt) {
-            columns.add("Ant");
+            columnsBuilder.add("Ant");
         }
-
         if (showMaven) {
-            columns.add("Maven");
+            columnsBuilder.add("Maven");
         }
-        columns.add("Description");
-        columns.add("Argument Type");
+        columnsBuilder.add("Description");
+        columnsBuilder.add("Argument Type");
+        columns = columnsBuilder;
 
-        Function<Option, String> descriptionFunction;
-
-        if (cl.hasOption(CLI) || !showAnt && !showMaven) {
+        if (addCLI || !showAnt && !showMaven) {
             descriptionFunction = o -> {
                 StringBuilder desc = new StringBuilder();
-            if (o.isDeprecated()) {
-                
desc.append("[").append(o.getDeprecated().toString()).append("] ");
-            }
-            return desc.append(StringUtils.defaultIfEmpty(o.getDescription(), 
"")).toString();
+                if (o.isDeprecated()) {
+                    
desc.append("[").append(o.getDeprecated().toString()).append("] ");
+                }
+                return 
desc.append(StringUtils.defaultIfEmpty(o.getDescription(), "")).toString();
             };
         } else if (showAnt) {
             descriptionFunction = o -> {
@@ -163,61 +181,56 @@ public final class Naming {
                 return desc.toString();
             };
         }
+    }
 
+    private void write() throws IOException {
         try (Writer underWriter = cl.getArgs().length != 0 ?
                 new FileWriter(cl.getArgs()[0], StandardCharsets.UTF_8) : new 
OutputStreamWriter(System.out, StandardCharsets.UTF_8)) {
             if (cl.hasOption(CSV)) {
-                printCSV(columns, filter, cl.hasOption(CLI), showMaven, 
showAnt, descriptionFunction, underWriter);
-            }
-            else {
-                printText(columns, filter, cl.hasOption(CLI), showMaven, 
showAnt, descriptionFunction, underWriter, width);
+                printCSV(underWriter);
+            } else {
+                printText(underWriter);
             }
         }
     }
 
-    private static List<String> fillColumns(final List<String> columns, final 
Option option, final boolean addCLI, final boolean showMaven,
-                                            final boolean showAnt, final 
Function<Option, String> descriptionFunction) {
-        AntOptionCollection antCollection = AntOptionCollection.INSTANCE;
-        MavenOptionCollection mavenCollection = MavenOptionCollection.INSTANCE;
 
+    private List<String> fillColumns(final Option option) {
+        List<String> columnsBuilder = new ArrayList<>();
         if (addCLI) {
             if (option.hasLongOpt()) {
-                columns.add("--" + option.getLongOpt());
+                columnsBuilder.add("--" + option.getLongOpt());
             } else {
-                columns.add("-" + option.getOpt());
+                columnsBuilder.add("-" + option.getOpt());
             }
         }
         if (showAnt) {
-            antCollection.getMappedOption(option).ifPresentOrElse(antOption -> 
columns.add(antOption.getExample()),
-                    () -> columns.add(" "));
+            antCollection.getMappedOption(option).ifPresentOrElse(antOption -> 
columnsBuilder.add(antOption.getExample()),
+                    () -> columnsBuilder.add(" "));
         }
         if (showMaven) {
-            
mavenCollection.getMappedOption(option).ifPresentOrElse(mavenOption -> 
columns.add(mavenOption.getExample()),
-                    () -> columns.add(" "));
+            
mavenCollection.getMappedOption(option).ifPresentOrElse(mavenOption -> 
columnsBuilder.add(mavenOption.getExample()),
+                    () -> columnsBuilder.add(" "));
         }
 
-        columns.add(descriptionFunction.apply(option));
-        columns.add(option.hasArgName() ? option.getArgName() : 
option.hasArgs() ? "Strings" : option.hasArg() ? "String" : "-- none --");
-        columns.add(option.hasArgName() ? option.getArgName() : 
option.hasArgs() ? "Strings" : option.hasArg() ? "String" : "-- none --");
-        columns.add(option.hasArgName() ? option.getArgName() : 
option.hasArgs() ? "Strings" : option.hasArg() ? "String" : "-- none --");
-        return columns;
+        columnsBuilder.add(descriptionFunction.apply(option));
+        columnsBuilder.add(option.hasArgName() ? option.getArgName() : 
option.hasArgs() ? "Strings" : option.hasArg() ? "String" : "-- none --");
+        return columnsBuilder;
     }
 
-    private static void printCSV(final List<String> columns, final 
Predicate<Option> filter, final boolean addCLI, final boolean showMaven,
-                                 final boolean showAnt, final Function<Option, 
String> descriptionFunction,
-                                 final Writer underWriter) throws IOException {
+    private void printCSV(final Appendable underWriter) throws IOException {
         try (CSVPrinter printer = new CSVPrinter(underWriter, 
CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.ALL).get())) {
             printer.printRecord(columns);
             for (Option option : OptionCollection.buildOptions().getOptions()) 
{
                 if (filter.test(option)) {
                     columns.clear();
-                    printer.printRecord(fillColumns(columns, option, addCLI, 
showMaven, showAnt, descriptionFunction));
+                    printer.printRecord(fillColumns(option));
                 }
             }
         }
     }
 
-    private static int[] calculateColumnWidth(final int width, final int 
columnCount, final List<List<String>> page) {
+    private int[] calculateColumnWidth(final int width, final int columnCount, 
final List<List<String>> page) {
         int[] columnWidth = new int[columnCount];
         for (List<String> row : page) {
             for (int i = 0; i < columnCount; i++) {
@@ -246,9 +259,7 @@ public final class Naming {
         return columnWidth;
     }
 
-    private static void printText(final List<String> columns, final 
Predicate<Option> filter, final boolean addCLI,
-                                  final boolean showMaven, final boolean 
showAnt,
-                                  final Function<Option, String> 
descriptionFunction, final Writer underWriter, final int width) throws 
IOException {
+    private void printText(final Appendable underWriter) throws IOException {
         List<List<String>> page = new ArrayList<>();
 
         int columnCount = columns.size();
@@ -256,7 +267,7 @@ public final class Naming {
 
         for (Option option : OptionCollection.buildOptions().getOptions()) {
             if (filter.test(option)) {
-                page.add(fillColumns(new ArrayList<>(), option, addCLI, 
showMaven, showAnt, descriptionFunction));
+                page.add(fillColumns(option));
             }
         }
         int[] columnWidth = calculateColumnWidth(width, columnCount, page);
diff --git 
a/apache-rat-tools/src/test/java/org/apache/rat/documentation/options/MavenOptionTest.java
 
b/apache-rat-tools/src/test/java/org/apache/rat/documentation/options/MavenOptionTest.java
index 38c65802..736e4360 100644
--- 
a/apache-rat-tools/src/test/java/org/apache/rat/documentation/options/MavenOptionTest.java
+++ 
b/apache-rat-tools/src/test/java/org/apache/rat/documentation/options/MavenOptionTest.java
@@ -27,9 +27,10 @@ import org.junit.jupiter.api.Test;
 public class MavenOptionTest {
     @Test
     void getDeprecatedTest() {
+        MavenOptionCollection mavenOptionCollection = new 
MavenOptionCollection();
         for (Option option : Arg.getOptions().getOptions()) {
             if (option.isDeprecated()) {
-                
MavenOptionCollection.INSTANCE.getMappedOption(option).ifPresent( mavenOption 
-> //
+                mavenOptionCollection.getMappedOption(option).ifPresent( 
mavenOption -> //
                         TextUtils.assertPatternNotInTarget("\\-\\- ", 
mavenOption.getDeprecated()));
             }
         }
diff --git 
a/apache-rat-tools/src/test/java/org/apache/rat/documentation/velocity/RatToolTest.java
 
b/apache-rat-tools/src/test/java/org/apache/rat/documentation/velocity/RatToolTest.java
index 52d5d571..7e2a6a6a 100644
--- 
a/apache-rat-tools/src/test/java/org/apache/rat/documentation/velocity/RatToolTest.java
+++ 
b/apache-rat-tools/src/test/java/org/apache/rat/documentation/velocity/RatToolTest.java
@@ -42,6 +42,9 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 public class RatToolTest {
     final RatTool underTest = new RatTool();
+    final CLIOptionCollection cliOptionCollection = new CLIOptionCollection();
+    final AntOptionCollection antOptionCollection = new AntOptionCollection();
+    final MavenOptionCollection mavenOptionCollection = new 
MavenOptionCollection();
 
     @Test
     void environmentVariables() {
@@ -57,13 +60,13 @@ public class RatToolTest {
     void antOptions() {
         Map<String, AntOption> options = underTest.antOptions();
         assertThat(options).isNotEmpty();
-        
assertThat(options.values()).containsExactlyInAnyOrderElementsOf(AntOptionCollection.INSTANCE.getMappedOptions().toList());
+        
assertThat(options.values()).containsExactlyInAnyOrderElementsOf(antOptionCollection.getMappedOptions().toList());
     }
 
     @Test
     void options() {
         List<Option> options = underTest.options();
-        
assertThat(options).isNotEmpty().containsExactlyInAnyOrderElementsOf(CLIOptionCollection.INSTANCE.getMappedOptions()
+        
assertThat(options).isNotEmpty().containsExactlyInAnyOrderElementsOf(cliOptionCollection.getMappedOptions()
                     .map(CLIOption::getOption).toList());
     }
 
@@ -71,14 +74,14 @@ public class RatToolTest {
     void cliOptions() {
         Map<String, CLIOption> options = underTest.cliOptions();
         assertThat(options).isNotEmpty();
-        
assertThat(options.values()).containsExactlyInAnyOrderElementsOf(CLIOptionCollection.INSTANCE.getMappedOptions().toList());
+        
assertThat(options.values()).containsExactlyInAnyOrderElementsOf(cliOptionCollection.getMappedOptions().toList());
     }
 
     @Test
     void mvnOptions() {
         Map<String, MavenOption> options = underTest.mvnOptions();
         assertThat(options).isNotEmpty();
-        
assertThat(options.values()).containsExactlyInAnyOrderElementsOf(MavenOptionCollection.INSTANCE.getMappedOptions().toList());
+        
assertThat(options.values()).containsExactlyInAnyOrderElementsOf(mavenOptionCollection.getMappedOptions().toList());
     }
 
     @Test
diff --git 
a/apache-rat-tools/src/test/java/org/apache/rat/tools/AntDocumentationTest.java 
b/apache-rat-tools/src/test/java/org/apache/rat/tools/AntDocumentationTest.java
index 07d1e12c..2200d200 100644
--- 
a/apache-rat-tools/src/test/java/org/apache/rat/tools/AntDocumentationTest.java
+++ 
b/apache-rat-tools/src/test/java/org/apache/rat/tools/AntDocumentationTest.java
@@ -45,14 +45,15 @@ class AntDocumentationTest {
 
     @BeforeEach
     void setup(@TempDir(cleanup = CleanupMode.NEVER) Path path) {
-        optionCollection = AntOptionCollection.INSTANCE;
+        optionCollection = new AntOptionCollection();
         testPath = path;
         underTest = new AntDocumentation(path.toFile());
     }
 
     @Test
     void writeAttributes() throws IOException {
-        List<AntOption> antOptions = options.getOptions().stream().map(opt -> 
new AntOption(optionCollection, opt)).toList();
+        AntOption.AntOptionBuilder builder = new 
AntOption.AntOptionBuilder().optionCollection(optionCollection);
+        List<AntOption> antOptions = options.getOptions().stream().map(opt -> 
builder.option(opt).build()).toList();
         underTest.writeAttributes(antOptions);
         File result = new File(testPath.toFile(), "report_attributes.txt");
         assertThat(result).exists();
@@ -63,7 +64,8 @@ class AntDocumentationTest {
 
     @Test
     void writeElements() throws IOException {
-        List<AntOption> antOptions = options.getOptions().stream().map(opt -> 
new AntOption(optionCollection, opt)).toList();
+        AntOption.AntOptionBuilder builder = new 
AntOption.AntOptionBuilder().optionCollection(optionCollection);
+        List<AntOption> antOptions = options.getOptions().stream().map(opt -> 
builder.option(opt).build()).toList();
         underTest.writeElements(antOptions);
         File result = new File(testPath.toFile(), "report_elements.txt");
         assertThat(result).exists();

Reply via email to