Better documentation and bugfix
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Thu, 20 Mar 2025 21:19:01 +0000 (23:19 +0200)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Thu, 20 Mar 2025 21:19:01 +0000 (23:19 +0200)
13 files changed:
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Option.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/ParameterCount.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Parser.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOption.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOptions.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/ExistenceType.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOption.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOptions.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FloatOption.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/IntegerOption.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/NullOption.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOption.java
src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOptions.java

index d591663..eb33fa7 100755 (executable)
@@ -10,239 +10,230 @@ import java.util.List;
 import static eu.svjatoslav.commons.cli_helper.parameter_parser.ParameterCount.NONE;
 import static java.lang.String.join;
 import static java.util.Collections.addAll;
-import static java.util.stream.Collectors.joining;
 
 /**
- * Represents an option that can be provided on CLI.
- * This class allows specifying whether the option is mandatory,
- * the parameter count, a description, and any aliases for the option.
+ * Represents a command-line option (a flag or switch), which can be configured with:
+ * <ul>
+ *   <li>whether it's mandatory</li>
+ *   <li>the number of parameters accepted</li>
+ *   <li>a textual description</li>
+ *   <li>aliases (the actual CLI flags, e.g., "--help" or "-h")</li>
+ * </ul>
  *
- * @param <T> type of value that this option returns.
- * @param <I> type of this option.
+ * @param <T> the type of object returned by {@link #getValue()}
+ * @param <I> the actual subclass type, used to enable fluent method chaining
  */
-public abstract class Option<T, I extends Option> {
+public abstract class Option<T, I extends Option<?, I>> {
 
     /**
-     * Purpose of this option, like: input image path, compression level, etc...
-     *
-     * Note: for describing option type there is {@link #describeFormat()}.
+     * Human-readable purpose of this option (e.g., "Input image path").
+     * For a description of the parameter format (e.g., "file", "integer"), see {@link #describeFormat()}.
      */
     public final String description;
 
-    /**
-     * List of arguments for this parameter.
-     */
+    /** The list of parameters provided on the command line for this option (if any). */
     public final List<String> parameters = new ArrayList<>();
+
+    /** How many parameters this option supports: NONE, ONE, or ONE_OR_MORE. */
     final ParameterCount parameterCount;
 
-    /**
-     * List of aliases for this option.
-     */
+    /** The aliases by which this option can be invoked (e.g. "-f", "--file"). */
     private final List<String> aliases = new ArrayList<>();
 
-    /**
-     * Indicates that at least one parameter is mandatory for this option.
-     */
-    protected boolean mandatory;
+    /** Whether this option is mandatory (i.e., must appear at least once on the CLI). */
+    protected boolean mandatory = false;
 
-    /**
-     * If this parameter was present in the commandline, then this boolean will
-     * be set to <code>true</code>.
-     */
-    private boolean isPresent;
+    /** Whether this option was actually present on the CLI. */
+    private boolean isPresent = false;
 
     /**
-     * Represents an option that can be provided on CLI.
-     * This class allows specifying whether the option is mandatory,
-     * the parameter count, a description, and any aliases for the option.
+     * Fully-custom constructor for an option.
      *
-     * @param mandatory        indicates whether the option is mandatory
-     * @param parameterCount   the number of parameters required for the option
-     * @param description      a description of the option
-     * @param aliases2         any additional aliases for the option
+     * @param mandatory      {@code true} if the option is required, {@code false} otherwise
+     * @param parameterCount the number of parameters required: NONE, ONE, or ONE_OR_MORE
+     * @param description    a textual description of the option
+     * @param aliases2       zero or more aliases (e.g. "-f", "--file")
      */
     public Option(final boolean mandatory,
-                  final ParameterCount parameterCount, final String description,
+                  final ParameterCount parameterCount,
+                  final String description,
                   final String... aliases2) {
-
         this.mandatory = mandatory;
         this.description = description;
         this.parameterCount = parameterCount;
-
-        // save aliases
         addAll(aliases, aliases2);
     }
 
-    public Option(final String description, final ParameterCount parameterCount) {
-        this.description = description;
-        this.parameterCount = parameterCount;
+    /**
+     * Simpler constructor that defaults to a non-mandatory option.
+     * You can make it mandatory later by calling {@link #setMandatory()}.
+     *
+     * @param description    a textual description of the option
+     * @param parameterCount the number of parameters required: NONE, ONE, or ONE_OR_MORE
+     * @param aliases2       zero or more aliases
+     */
+    public Option(final String description,
+                  final ParameterCount parameterCount,
+                  final String... aliases2) {
+        this(false, parameterCount, description, aliases2);
     }
 
     /**
-     * Adds additional aliases to the option.
+     * Adds additional aliases to this option for user convenience.
      *
-     * @param aliasArray    an array of strings representing the aliases to be added
-     * @return the modified option object
+     * @param aliasArray additional aliases (e.g., "-f", "--file")
+     * @return this option (for method chaining)
      */
     @SuppressWarnings("unchecked")
     public I addAliases(final String... aliasArray) {
-
-        // save aliases
         addAll(aliases, aliasArray);
-
         return (I) this;
     }
 
     /**
-     * @param parameterString parameter to add
-     * @return <code>true</code> if no errors were found. <code>false</code>
-     * otherwise.
+     * Adds a parameter to this option, validating it against {@link #isValid(String)}.
+     *
+     * @param parameterString the parameter string to add
+     * @return {@code true} if the parameter was valid and added, otherwise {@code false}
      */
     public boolean addParameter(final String parameterString) {
-        // check if arguments are allowed for this parameter
+        // Check if this option is supposed to have parameters at all
         if (parameterCount.equals(NONE)) {
-            System.out
-                    .println("Error! No parameters are allowed for option(s): "
-                            + getAliasesAsString());
+            System.out.println("Error! No parameters are allowed for option(s): "
+                    + getAliasesAsString());
             return false;
         }
 
-        // check if multiple arguments are allowed
-        if ((!parameters.isEmpty())
-                && (parameterCount.equals(ParameterCount.ONE))) {
-            System.out
-                    .println("Error! Only single parameter is allowed for argument(s): "
-                            + getAliasesAsString());
+        // If only ONE parameter is allowed, but we already have one
+        if ((!parameters.isEmpty()) && parameterCount.equals(ParameterCount.ONE)) {
+            System.out.println("Error! Only one parameter is allowed for argument(s): "
+                    + getAliasesAsString());
             return false;
         }
 
+        // Validate the parameter itself
         if (isValid(parameterString)) {
             parameters.add(parameterString);
             return true;
         } else {
-            System.out.println("Error! Invalid parameter type for \"" + parameterString
-                    + "\". It shall be " + describeFormat() + ".");
+            System.out.println("Error! Invalid parameter \"" + parameterString
+                    + "\". It should be " + describeFormat() + ".");
             return false;
         }
     }
 
     /**
-     * @return Single line parameter type description. For example: "file", "date", "integer", "regular expression", etc..
-     * <p>
-     * Note: for argument purpose description there is {@link #description}
+     * Describes the kind or format of the expected parameter(s), e.g. "File", "Integer", etc.
+     *
+     * @return a short string describing the parameter format
      */
     public abstract String describeFormat();
 
     /**
-     * @return aliases for this parameter as string.
+     * Returns this option's aliases as a comma-separated string (e.g. "-f, --file").
      */
     public String getAliasesAsString() {
-        return join(", ", aliases);
+        return aliases.isEmpty() ? "<no aliases>" : join(", ", aliases);
     }
 
     /**
-     * Returns the help message for this parameter.
+     * Returns a help message that includes the aliases, whether the option is mandatory,
+     * the format, and a brief description.
      *
-     * @return the help message as a string.
+     * @return a descriptive help string
      */
     public String getHelp() {
-        final StringBuilder result = new StringBuilder();
-
-        // first line
+        StringBuilder result = new StringBuilder();
+        // First line: aliases plus (mandatory?, format)
         result.append(getAliasesAsString());
         if (!NONE.equals(parameterCount)) {
-            result
-                    .append(" (")
+            result.append(" (")
                     .append(isMandatory() ? "mandatory, " : "")
                     .append(describeFormat())
                     .append(")");
-
-            if (parameterCount.equals(ParameterCount.ONE_OR_MORE))
+            if (ParameterCount.ONE_OR_MORE.equals(parameterCount)) {
                 result.append("...");
+            }
         }
         result.append("\n");
-
-        // second line
-        result.append("    " + description + "\n");
-
+        // Second line: indentation plus description
+        result.append("    ").append(description).append("\n");
         return result.toString();
     }
 
     /**
-     * Returns the value of the object.
+     * Returns the parsed value (usually constructed from {@link #parameters}).
      *
-     * @return the value of the object.
+     * @return the parsed value as the generic type T.
+     * @throws RuntimeException if the parameters are insufficient or invalid in a subclass.
      */
     public abstract T getValue();
 
+    /**
+     * @return {@code true} if this option is mandatory.
+     */
     public boolean isMandatory() {
         return mandatory;
     }
 
     /**
-     * @return <code>true</code> if this parameter was present in the commandline.
+     * @return {@code true} if this option was present on the command line.
      */
     public boolean isPresent() {
         return isPresent;
     }
 
     /**
-     * Sets the present status of this parameter.
+     * Marks this option as present or not present.
      *
-     * @param present <code>true</code> if this parameter is present in the command line,
-     *                <code>false</code> otherwise.
+     * @param present {@code true} if it was found in the CLI arguments, else {@code false}.
      */
     protected void setPresent(final boolean present) {
         this.isPresent = present;
     }
 
     /**
-     * @param alias alias to check against
-     * @return <code>true</code> if given alias is registered for this
-     * parameter.
+     * Checks if a given alias matches this option.
+     *
+     * @param alias the alias to check
+     * @return {@code true} if the alias is registered for this option
      */
     public boolean matchesAlias(final String alias) {
         return aliases.contains(alias);
-
     }
 
     /**
-     * Notifies this option that no more parameters will follow.
-     * This gives option chance to verify if this is ok.
+     * Called when no more arguments can be added to this option, giving it a chance
+     * to verify correct usage (e.g., check if required parameters are missing).
      *
-     * @return <code>true</code> if no errors were found. <code>false</code>
-     * otherwise.
+     * @return {@code true} if the usage so far is valid; otherwise {@code false}.
      */
     public boolean noMoreArguments() {
-
-        if ((!parameterCount.equals(NONE))
-                && (parameters.isEmpty())) {
-
+        // If we expect at least one parameter but none were provided
+        if (!parameterCount.equals(NONE) && parameters.isEmpty()) {
             System.out.println("Error! " + getAliasesAsString()
-                    + " require at least one parameter.");
-
+                    + " requires at least one parameter.");
             return false;
         }
         return true;
     }
 
     /**
-     * Sets the option as mandatory. This means that the option must be provided by the user
-     * in order for the program to run successfully.
+     * Sets this option as mandatory.
      *
-     * @return The updated instance of the option.
+     * @return this option, for method chaining
      */
     @SuppressWarnings("unchecked")
     public I setMandatory() {
-        mandatory = true;
+        this.mandatory = true;
         return (I) this;
     }
 
     /**
-     * @param value value to validate
-     * @return <code>true</code> if value is correct, <code>false</code>
-     * otherwise.
+     * Checks if a single parameter string is valid for this option.
+     *
+     * @param value the parameter string to test
+     * @return {@code true} if valid; {@code false} otherwise
      */
     public abstract boolean isValid(String value);
-
 }
index 0d74b3f..1a30fe8 100755 (executable)
@@ -5,23 +5,15 @@
 package eu.svjatoslav.commons.cli_helper.parameter_parser;
 
 /**
- * This enumeration is used to define how many parameters
- * does particular commandline option accept.
+ * Defines how many parameters a command-line option can accept.
  */
 public enum ParameterCount {
-
-    /**
-     * Option has no parameters.
-     */
+    /** Option has no parameters. */
     NONE,
 
-    /**
-     * Option has exactly one mandatory parameter.
-     */
+    /** Option has exactly one parameter. */
     ONE,
 
-    /**
-     * Option must have one or more parameters.
-     */
+    /** Option can have one or more parameters. */
     ONE_OR_MORE
-}
+}
\ No newline at end of file
index d307ea3..41c6b40 100755 (executable)
 package eu.svjatoslav.commons.cli_helper.parameter_parser;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
- * Single commandline parameter can have any amount of arguments.
+ * This class parses command-line arguments against a set of registered {@link Option} objects.
+ * <p>
+ * Usage:
+ * <pre>{@code
+ *   Parser parser = new Parser();
+ *   FileOption fileOpt = parser.add(new FileOption("Input file").mustExist())
+ *                              .addAliases("-f", "--file")
+ *                              .setMandatory();
+ *   parser.parse(args);
+ *   if (!parser.checkSuccess()) {
+ *       parser.showHelp();
+ *       System.exit(1);
+ *   }
+ *   File inputFile = fileOpt.getValue();
+ * }</pre>
  */
 public class Parser {
 
-    private final ArrayList<Option<?, ? extends Option>> options = new ArrayList<>();
-
-    public <E extends Option> E add(final E parameter) {
-        options.add(parameter);
-        return parameter;
-    }
+    private final List<Option<?, ? extends Option<?, ?>>> options = new ArrayList<>();
 
     /**
-     * @return <code>true</code> if no errors were found. <code>false</code>
-     * otherwise.
+     * Registers an option with this parser.
+     *
+     * @param option the option to be added
+     * @param <E>    the concrete type of the option
+     * @return the same option object, for chaining
      */
-    private boolean checkMandatoryArgumentsPresent() {
-
-        for (final Option option : options)
-            if (option.isMandatory() && (!option.isPresent())) {
-                System.out.println("Error! Mandatory parameter ("
-                        + option.getAliasesAsString() + ") is not specified.");
-                return false;
-            }
-
-        return true;
+    public <E extends Option<?, E>> E add(final E option) {
+        options.add(option);
+        return option;
     }
 
     /**
-     * Return parameter by given alias or <code>null</code> if no parameter
-     * exists for given alias.
+     * Looks up an option by alias.
      *
-     * @param alias parameter alias
-     * @return found parameter or <code>null</code> if parameter was not found.
+     * @param alias the alias to search for (e.g., "-f" or "--file")
+     * @return the matching option, or {@code null} if not found
      */
-    public Option findParameterByAlias(final String alias) {
-
-        for (final Option option : options)
-            if (option.matchesAlias(alias))
+    public Option<?, ?> findParameterByAlias(final String alias) {
+        for (final Option<?, ?> option : options) {
+            if (option.matchesAlias(alias)) {
                 return option;
-
+            }
+        }
         return null;
     }
 
     /**
-     * @param args commandline arguments
-     * @return <code>true</code> if no errors were found. <code>false</code>
-     * otherwise.
+     * Parses the provided command-line arguments, matching them to registered options and their parameters.
+     *
+     * @param args command-line arguments (usually from main(String[]))
+     * @return {@code true} if parsing succeeded without errors; otherwise {@code false}.
      */
     public boolean parse(final String[] args) {
-
-        Option currentOption = null;
+        Option<?, ?> currentOption = null;
 
         for (final String argument : args) {
+            Option<?, ?> optionForAlias = findParameterByAlias(argument);
 
-            final Option optionForAlias = findParameterByAlias(argument);
             if (optionForAlias == null) {
+                // If this argument is not a recognized option alias, treat it as a parameter to the current option
                 if (currentOption == null) {
-                    System.out.println("Unknown commandline parameter: "
-                            + argument);
+                    System.out.println("Unknown command-line parameter: " + argument);
                     return false;
                 }
-
-                if (!currentOption.addParameter(argument))
+                // Attempt to add this argument as a parameter to the current option
+                if (!currentOption.addParameter(argument)) {
                     return false;
-
+                }
             } else {
-                if (currentOption != null)
-                    if (!currentOption.noMoreArguments())
+                // We found a recognized option
+                // First, let the previous option finalize (check if it has all needed params, etc.)
+                if (currentOption != null) {
+                    if (!currentOption.noMoreArguments()) {
                         return false;
-
+                    }
+                }
+                // Switch to the newly recognized option
                 optionForAlias.setPresent(true);
                 currentOption = optionForAlias;
             }
+        }
 
+        // Finalize the last option (if any)
+        if (currentOption != null) {
+            if (!currentOption.noMoreArguments()) {
+                return false;
+            }
         }
 
+        // Finally, check mandatory options
         return checkMandatoryArgumentsPresent();
     }
 
-    public void showHelp() {
-        System.out.println("Available commandline arguments:");
-        for (final Option option : options)
-            System.out.println(option.getHelp());
+    /**
+     * Checks whether all mandatory options were present.
+     *
+     * @return {@code true} if all mandatory options are present, otherwise {@code false}.
+     */
+    private boolean checkMandatoryArgumentsPresent() {
+        for (final Option<?, ?> option : options) {
+            if (option.isMandatory() && !option.isPresent()) {
+                System.out.println("Error! Mandatory parameter ("
+                        + option.getAliasesAsString() + ") is not specified.");
+                return false;
+            }
+        }
+        return true;
     }
 
-}
+    /**
+     * A convenience method to see if the last parse succeeded. If you stored the result of {@link #parse(String[])} in a
+     * boolean, you can also just check that.
+     *
+     * @return {@code true} if all mandatory options are present (and no parse errors occurred).
+     */
+    public boolean checkSuccess() {
+        return checkMandatoryArgumentsPresent();
+    }
+
+    /**
+     * Prints all available options, their formats, and their descriptions. Usually called upon parse failure.
+     */
+    public void showHelp() {
+        System.out.println("Available command-line arguments:");
+        for (final Option<?, ?> option : options) {
+            System.out.print(option.getHelp());
+        }
+    }
+}
\ No newline at end of file
index ee52751..63c1714 100755 (executable)
@@ -9,58 +9,50 @@ import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
 
 import java.io.File;
 
-
 /**
- * This class is used to define commandline option which accepts directory as parameter.
+ * Represents a command-line option that accepts exactly one parameter interpreted as a directory path.
  */
 public class DirectoryOption extends Option<File, DirectoryOption> {
 
-    /**
-     * This enum is used to define if directory shall exist in filesystem or not.
-     */
+    /** Defines whether the directory must exist, must not exist, or if it does not matter. */
     private ExistenceType existenceType = ExistenceType.DOES_NOT_MATTER;
 
     /**
-     * Constructor.
+     * Creates a DirectoryOption object with a specified description.
      *
-     * @param description Description of the option.
+     * @param description a brief description of what this directory option is for.
      */
     public DirectoryOption(final String description) {
         super(description, ParameterCount.ONE);
     }
 
     @Override
-    public java.lang.String describeFormat() {
+    public String describeFormat() {
         switch (existenceType) {
-            case MUST_EXIST:
-                return "Existing directory.";
-            case MUST_NOT_EXIST:
-                return "Non-existing directory.";
-            default:
-                return "Directory.";
+            case MUST_EXIST:     return "Existing directory.";
+            case MUST_NOT_EXIST: return "Non-existing directory.";
+            default:             return "Directory.";
         }
     }
 
     /**
-     * Retrieves the value of the option as a {@link File} object.
+     * Returns the directory as a {@link File} object.
      *
-     * @return The value of the option as a {@link File} object.
-     * @throws RuntimeException if the option does not have exactly 1 argument.
+     * @throws RuntimeException if the user did not provide exactly one parameter.
      */
     @Override
     public File getValue() {
-
-        if (parameters.size() != 1)
-            throw new RuntimeException("Parameter " + description
-                    + " shall have exactly 1 argument.");
-
+        if (parameters.size() != 1) {
+            throw new RuntimeException("Parameter '" + description
+                    + "' must have exactly 1 argument.");
+        }
         return new File(parameters.get(0));
     }
 
     /**
-     * This method sets that directory shall exist.
+     * Requires that the directory must already exist.
      *
-     * @return This object.
+     * @return this DirectoryOption instance for chaining
      */
     public DirectoryOption mustExist() {
         existenceType = ExistenceType.MUST_EXIST;
@@ -68,9 +60,9 @@ public class DirectoryOption extends Option<File, DirectoryOption> {
     }
 
     /**
-     * This method sets that directory shall not exist.
+     * Requires that the directory must not already exist.
      *
-     * @return This object.
+     * @return this DirectoryOption instance for chaining
      */
     public DirectoryOption mustNotExist() {
         existenceType = ExistenceType.MUST_NOT_EXIST;
@@ -78,32 +70,31 @@ public class DirectoryOption extends Option<File, DirectoryOption> {
     }
 
     /**
-     * This method checks if a provided directory path is valid based on the specified existence type.
+     * Checks whether the provided path is valid based on the {@link ExistenceType}.
      *
-     * @param value The directory path to validate.
-     * @return True if the directory path is valid according to the existence type, otherwise false.
+     * @param value the directory path to validate
+     * @return {@code true} if valid, otherwise {@code false}
      */
     @Override
-    public boolean isValid(final java.lang.String value) {
+    public boolean isValid(final String value) {
         final File file = new File(value);
 
-        if (existenceType == ExistenceType.MUST_EXIST) {
-            return file.exists() && file.isDirectory();
-        }
+        switch (existenceType) {
+            case MUST_EXIST:
+                return file.exists() && file.isDirectory();
 
-        if (existenceType == ExistenceType.MUST_NOT_EXIST) {
-            return !file.exists();
-        }
+            case MUST_NOT_EXIST:
+                return !file.exists();
 
-        if (existenceType == ExistenceType.DOES_NOT_MATTER) {
-            if (file.exists())
-                if (file.isFile())
+            case DOES_NOT_MATTER:
+                // If it exists and is a file, it's invalid
+                if (file.exists() && file.isFile()) {
                     return false;
+                }
+                return true;
 
-            return true;
+            default:
+                return false;
         }
-
-        return false;
     }
-
-}
+}
\ No newline at end of file
index d012cf9..fb0d923 100755 (executable)
@@ -12,85 +12,81 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 /**
- * DirectoryOptions class represents a command-line option for one or more directories.
+ * Represents a command-line option that accepts one or more directory paths.
  */
 public class DirectoryOptions extends Option<List<File>, DirectoryOptions> {
 
-    /**
-     * This enum is used to define if resource denoted by particular option parameter shall exist or not.
-     * <p>
-     * This allows to specify for example if directory shall exist or not.
-     */
+    /** Defines whether each directory must exist, must not exist, or if it does not matter. */
     private ExistenceType existenceType = ExistenceType.DOES_NOT_MATTER;
 
     /**
-     * Creates a new DirectoryOptions object with the given description.
+     * Creates a DirectoryOptions object with a specified description, requiring one or more directories.
      *
-     * @param description The description of the directory options.
+     * @param description a brief description of what these directories represent.
      */
     public DirectoryOptions(final String description) {
         super(description, ParameterCount.ONE_OR_MORE);
     }
 
-    /**
-     * Returns a string describing the format of the option.
-     *
-     * @return A string describing the format of the option.
-     */
     @Override
     public String describeFormat() {
         switch (existenceType) {
-            case MUST_EXIST:
-                return "One to many existing directories.";
-            case MUST_NOT_EXIST:
-                return "One to many non-existing directories.";
-            default:
-                return "One to many directories.";
+            case MUST_EXIST:     return "One to many existing directories.";
+            case MUST_NOT_EXIST: return "One to many non-existing directories.";
+            default:             return "One to many directories.";
         }
     }
 
     /**
-     * Returns the value of the option as a list of File objects.
-     *
-     * @return The value of the option as a list of File objects.
+     * Returns the directories as a list of {@link File} objects.
      */
     @Override
     public List<File> getValue() {
         return parameters.stream().map(File::new).collect(Collectors.toList());
     }
 
+    /**
+     * Requires that each directory must exist.
+     *
+     * @return this DirectoryOptions instance
+     */
     public DirectoryOptions mustExist() {
         existenceType = ExistenceType.MUST_EXIST;
         return this;
     }
 
+    /**
+     * Requires that each directory must not exist.
+     *
+     * @return this DirectoryOptions instance
+     */
     public DirectoryOptions mustNotExist() {
         existenceType = ExistenceType.MUST_NOT_EXIST;
         return this;
     }
 
-
+    /**
+     * Validates each directory path against the specified {@link ExistenceType}.
+     */
     @Override
     public boolean isValid(final String value) {
         final File file = new File(value);
 
-        if (existenceType == ExistenceType.MUST_EXIST) {
-            return file.exists() && file.isDirectory();
-        }
+        switch (existenceType) {
+            case MUST_EXIST:
+                return file.exists() && file.isDirectory();
 
-        if (existenceType == ExistenceType.MUST_NOT_EXIST) {
-            return !file.exists();
-        }
+            case MUST_NOT_EXIST:
+                return !file.exists();
 
-        if (existenceType == ExistenceType.DOES_NOT_MATTER) {
-            if (file.exists())
-                if (file.isFile())
+            case DOES_NOT_MATTER:
+                if (file.exists() && file.isFile()) {
                     return false;
+                }
+                return true;
 
-            return true;
+            default:
+                return false;
         }
-
-        return false;
     }
-
-}
+}
\ No newline at end of file
index e001b0d..a3cccc1 100755 (executable)
@@ -5,25 +5,15 @@
 package eu.svjatoslav.commons.cli_helper.parameter_parser.parameter;
 
 /**
- * This enum is used to define if resource denoted by particular option parameter shall exist or not.
- * <p>
- * This allows to specify for example if directory shall exist or not.
+ * Defines whether a file/directory resource must exist, must not exist, or if it does not matter.
  */
 public enum ExistenceType {
-
-    /**
-     * Resource shall exist.
-     */
+    /** Resource shall exist. */
     MUST_EXIST,
 
-    /**
-     * Resource shall not exist.
-     */
+    /** Resource shall not exist. */
     MUST_NOT_EXIST,
 
-    /**
-     * Resource existence does not matter.
-     */
-    DOES_NOT_MATTER;
-
-}
+    /** Resource existence does not matter. */
+    DOES_NOT_MATTER
+}
\ No newline at end of file
index c10ec1e..00c295d 100755 (executable)
@@ -10,65 +10,85 @@ import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
 import java.io.File;
 
 /**
- * This class represents commandline option which accepts exactly one parameter
- * which is a file.
+ * Represents a command-line option that accepts exactly one parameter which is interpreted as a file path.
+ * By default, {@link ExistenceType#DOES_NOT_MATTER} is used (i.e., the file may or may not exist).
  */
 public class FileOption extends Option<File, FileOption> {
 
+    /** Specifies whether the file must exist, must not exist, or does not matter. */
     private ExistenceType existenceType = ExistenceType.DOES_NOT_MATTER;
 
+    /**
+     * Creates a FileOption requiring exactly one parameter that represents a file.
+     *
+     * @param description a brief description of what this option is for (e.g., "Path to input file").
+     */
     public FileOption(final String description) {
         super(description, ParameterCount.ONE);
     }
 
-    protected static boolean validateFile(ExistenceType existenceType, String value) {
-        final File file = new File(value);
+    /**
+     * Checks whether the given file path is valid according to the specified {@link ExistenceType}.
+     *
+     * @param existenceType  the required existence status for the file
+     * @param path           the file path to validate
+     * @return {@code true} if the path meets the existence requirement and is not a directory when it must be a file.
+     */
+    protected static boolean isFileValid(ExistenceType existenceType, String path) {
+        final File file = new File(path);
 
-        if (existenceType == ExistenceType.MUST_EXIST) {
-            return file.exists() && file.isFile();
-        }
+        switch (existenceType) {
+            case MUST_EXIST:
+                return file.exists() && file.isFile();
 
-        if (existenceType == ExistenceType.MUST_NOT_EXIST) {
-            return !file.exists();
-        }
+            case MUST_NOT_EXIST:
+                return !file.exists();
 
-        if (existenceType == ExistenceType.DOES_NOT_MATTER) {
-            if (file.exists())
-                if (file.isDirectory())
+            case DOES_NOT_MATTER:
+                // If the file exists, ensure it's not a directory
+                if (file.exists() && file.isDirectory()) {
                     return false;
+                }
+                return true;
 
-            return true;
+            default:
+                return false;
         }
-
-        return false;
     }
 
+    /**
+     * Provides a short description of the expected format (e.g., "Existing file", "Non-existing file", or "File").
+     *
+     * @return a string describing the format of this file parameter.
+     */
     @Override
-    public java.lang.String describeFormat() {
+    public String describeFormat() {
         switch (existenceType) {
-            case MUST_EXIST:
-                return "Existing file.";
-            case MUST_NOT_EXIST:
-                return "Non-existing file.";
-            default:
-                return "File.";
+            case MUST_EXIST:     return "Existing file.";
+            case MUST_NOT_EXIST: return "Non-existing file.";
+            default:             return "File.";
         }
     }
 
+    /**
+     * Returns the file chosen by the user (as a {@link File} object).
+     *
+     * @return a {@link File} object constructed from the single parameter.
+     * @throws RuntimeException if the option does not have exactly 1 parameter.
+     */
     @Override
     public File getValue() {
-
-        if (parameters.size() != 1)
-            throw new RuntimeException("Parameter " + description
-                    + " shall have exactly 1 argument.");
-
+        if (parameters.size() != 1) {
+            throw new RuntimeException("Parameter '" + description
+                    + "' must have exactly 1 argument.");
+        }
         return new File(parameters.get(0));
     }
 
     /**
-     * This method sets that file shall exist.
+     * Enforces that the file path must point to an existing file.
      *
-     * @return This object.
+     * @return this FileOption instance, for method chaining
      */
     public FileOption mustExist() {
         existenceType = ExistenceType.MUST_EXIST;
@@ -76,18 +96,23 @@ public class FileOption extends Option<File, FileOption> {
     }
 
     /**
-     * This method sets that file shall not exist.
+     * Enforces that the file path must not exist.
      *
-     * @return This object.
+     * @return this FileOption instance, for method chaining
      */
     public FileOption mustNotExist() {
         existenceType = ExistenceType.MUST_NOT_EXIST;
         return this;
     }
 
+    /**
+     * Validates the given parameter against the {@link ExistenceType} rule.
+     *
+     * @param value the file path to validate
+     * @return {@code true} if the file path meets the existence requirement
+     */
     @Override
-    public boolean isValid(final java.lang.String value) {
-        return validateFile(existenceType, value);
+    public boolean isValid(final String value) {
+        return isFileValid(existenceType, value);
     }
-
-}
+}
\ No newline at end of file
index 9534224..2d0e8ab 100755 (executable)
@@ -11,41 +11,51 @@ import java.io.File;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import static eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.FileOption.validateFile;
-
 /**
- * This class represents commandline option which accepts one or more parameters
- * which are files.
+ * Represents a command-line option that accepts one or more file paths.
  */
 public class FileOptions extends Option<List<File>, FileOptions> {
 
+    /** Specifies whether each file must exist, must not exist, or does not matter. */
     private ExistenceType existenceType = ExistenceType.DOES_NOT_MATTER;
 
+    /**
+     * Constructs a FileOptions object.
+     *
+     * @param description a brief description of the option's purpose.
+     */
     public FileOptions(final String description) {
         super(description, ParameterCount.ONE_OR_MORE);
     }
 
+    /**
+     * Provides a short description of the expected file format(s).
+     *
+     * @return either "One to many existing files.", "One to many non-existing files.", or "One to many files."
+     */
     @Override
     public String describeFormat() {
         switch (existenceType) {
-            case MUST_EXIST:
-                return "One to many existing files.";
-            case MUST_NOT_EXIST:
-                return "One to many non-existing files.";
-            default:
-                return "One to many files.";
+            case MUST_EXIST:     return "One to many existing files.";
+            case MUST_NOT_EXIST: return "One to many non-existing files.";
+            default:             return "One to many files.";
         }
     }
 
+    /**
+     * Returns the list of file paths as {@link File} objects.
+     *
+     * @return a list of {@link File} objects corresponding to user input.
+     */
     @Override
     public List<File> getValue() {
         return parameters.stream().map(File::new).collect(Collectors.toList());
     }
 
     /**
-     * This method is used to define that file shall exist in filesystem.
+     * Requires that each file must already exist.
      *
-     * @return This object.
+     * @return this FileOptions instance for chaining
      */
     public FileOptions mustExist() {
         existenceType = ExistenceType.MUST_EXIST;
@@ -53,18 +63,20 @@ public class FileOptions extends Option<List<File>, FileOptions> {
     }
 
     /**
-     * This method is used to define that file shall not exist in filesystem.
+     * Requires that each file must not already exist.
      *
-     * @return This object.
+     * @return this FileOptions instance for chaining
      */
     public FileOptions mustNotExist() {
         existenceType = ExistenceType.MUST_NOT_EXIST;
         return this;
     }
 
+    /**
+     * Validates a single file path against the configured existence type.
+     */
     @Override
     public boolean isValid(final String value) {
-        return validateFile(existenceType, value);
+        return FileOption.isFileValid(existenceType, value);
     }
-
-}
+}
\ No newline at end of file
index 1ab5ec4..8aaca36 100644 (file)
@@ -1,35 +1,61 @@
+/*
+ * Svjatoslav Commons - shared library of common functionality. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
 package eu.svjatoslav.commons.cli_helper.parameter_parser.parameter;
 
 import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
 import eu.svjatoslav.commons.cli_helper.parameter_parser.ParameterCount;
 
+/**
+ * Represents a command-line option that accepts exactly one floating-point parameter.
+ */
 public class FloatOption extends Option<Float, FloatOption> {
 
-        public FloatOption(final String description) {
-            super(description, ParameterCount.ONE);
-        }
+    /**
+     * Constructs a FloatOption with a brief description and exactly one parameter.
+     *
+     * @param description a brief description of the option (e.g., "Scale factor").
+     */
+    public FloatOption(final String description) {
+        super(description, ParameterCount.ONE);
+    }
 
-        @Override
-        public java.lang.String describeFormat() {
-            return "Floating point number. Example: 3.14";
-        }
+    /**
+     * Describes the expected format ("Floating point number").
+     */
+    @Override
+    public String describeFormat() {
+        return "Floating point number. Example: 3.14";
+    }
 
-        @Override
-        public Float getValue() {
-            if (parameters.size() != 1)
-                throw new RuntimeException("Parameter " + description
-                        + " shall have exactly 1 argument.");
-            return Float.parseFloat(parameters.get(0));
+    /**
+     * Returns the float value specified by the user.
+     *
+     * @throws RuntimeException if the user did not provide exactly one parameter.
+     */
+    @Override
+    public Float getValue() {
+        if (parameters.size() != 1) {
+            throw new RuntimeException("Parameter '" + description
+                    + "' must have exactly 1 argument.");
         }
+        return Float.parseFloat(parameters.get(0));
+    }
 
-        @Override
-        public boolean isValid(final java.lang.String value) {
-            try {
-                java.lang.Float.valueOf(value);
-                return true;
-            } catch (final NumberFormatException e) {
-                return false;
-            }
+    /**
+     * Checks if the given string can be parsed as a float.
+     *
+     * @param value the string to validate
+     * @return {@code true} if the string is a valid float, otherwise {@code false}
+     */
+    @Override
+    public boolean isValid(final String value) {
+        try {
+            Float.valueOf(value);
+            return true;
+        } catch (final NumberFormatException e) {
+            return false;
         }
-}
-
+    }
+}
\ No newline at end of file
index 592ab00..3fd6ead 100755 (executable)
@@ -8,32 +8,51 @@ import eu.svjatoslav.commons.cli_helper.parameter_parser.ParameterCount;
 import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
 
 /**
- * This class represents commandline option which accepts exactly one parameter
- * which is an integer.
+ * Represents a command-line option that accepts exactly one parameter interpreted as an integer.
  */
 public class IntegerOption extends Option<Integer, IntegerOption> {
 
+    /**
+     * Constructs an IntegerOption with exactly one parameter required.
+     *
+     * @param description a brief description of what this option represents.
+     */
     public IntegerOption(final String description) {
         super(description, ParameterCount.ONE);
     }
 
+    /**
+     * Describes the expected format ("Integer.").
+     */
     @Override
-    public java.lang.String describeFormat() {
+    public String describeFormat() {
         return "Integer.";
     }
 
+    /**
+     * Returns the integer value specified by the user.
+     *
+     * @throws RuntimeException if the user did not provide exactly one parameter.
+     */
     @Override
     public Integer getValue() {
-        if (parameters.size() != 1)
-            throw new RuntimeException("Parameter " + description
-                    + " shall have exactly 1 argument.");
+        if (parameters.size() != 1) {
+            throw new RuntimeException("Parameter '" + description
+                    + "' must have exactly 1 argument.");
+        }
         return Integer.parseInt(parameters.get(0));
     }
 
+    /**
+     * Checks whether the given string can be parsed as an integer.
+     *
+     * @param value the string to validate
+     * @return {@code true} if the string is a valid integer, otherwise {@code false}
+     */
     @Override
-    public boolean isValid(final java.lang.String value) {
+    public boolean isValid(final String value) {
         try {
-            java.lang.Integer.valueOf(value);
+            Integer.valueOf(value);
             return true;
         } catch (final NumberFormatException e) {
             return false;
index 9b5ad88..cdf6583 100755 (executable)
@@ -8,27 +8,45 @@ import eu.svjatoslav.commons.cli_helper.parameter_parser.ParameterCount;
 import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
 
 /**
- * This class represents commandline option which accepts exactly zero parameters.
+ * Represents a command-line option that accepts exactly zero parameters.
+ * Often used for flags that are either present or absent.
  */
 public class NullOption extends Option<Boolean, NullOption> {
 
+    /**
+     * Creates a NullOption (e.g. a boolean flag) that requires no parameters.
+     *
+     * @param description a brief description of what this option does (e.g., "Enable debug mode").
+     */
     public NullOption(final String description) {
         super(description, ParameterCount.NONE);
     }
 
+    /**
+     * Describes the expected format of this option (i.e., no parameters).
+     *
+     * @return the string "None."
+     */
     @Override
-    public java.lang.String describeFormat() {
+    public String describeFormat() {
         return "None.";
     }
 
+    /**
+     * Returns whether this option was present on the command line.
+     *
+     * @return {@code true} if the user specified this option, otherwise {@code false}.
+     */
     @Override
     public Boolean getValue() {
         return isPresent();
     }
 
+    /**
+     * Always returns {@code true}, since this option has no parameters and needs no validation.
+     */
     @Override
-    public boolean isValid(final java.lang.String value) {
+    public boolean isValid(final String value) {
         return true;
     }
-
-}
+}
\ No newline at end of file
index d7cb3e7..fa7f102 100755 (executable)
@@ -8,42 +8,68 @@ import eu.svjatoslav.commons.cli_helper.parameter_parser.ParameterCount;
 import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
 
 /**
- * This class represents commandline option which accepts exactly one parameter
- * which is a string.
+ * Represents a command-line option that accepts exactly one string parameter.
+ * An optional default value can be provided; if so, this option is considered "present" even without user input.
  */
 public class StringOption extends Option<String, StringOption> {
 
+    /**
+     * Default value to return if the user does not provide a parameter.
+     * If non-null, this option is automatically considered present.
+     */
     public final String defaultValue;
 
+    /**
+     * Constructs a StringOption with no default value.
+     *
+     * @param description a brief description of what this option does.
+     */
     public StringOption(final String description) {
         super(description, ParameterCount.ONE);
-        defaultValue = null;
+        this.defaultValue = null;
     }
+
+    /**
+     * Constructs a StringOption with a specified default value.
+     *
+     * @param description  a brief description of what this option does.
+     * @param defaultValue the default string to use if the user does not supply a parameter.
+     */
     public StringOption(final String description, String defaultValue) {
         super(description, ParameterCount.ONE);
         this.defaultValue = defaultValue;
+
+        // If a default value is provided, mark this option as present by default.
         this.setPresent(true);
     }
 
     @Override
-    public java.lang.String describeFormat() {
+    public String describeFormat() {
         return "String.";
     }
 
+    /**
+     * Returns the string parameter or the default value if none was provided.
+     *
+     * @throws RuntimeException if multiple parameters were provided.
+     */
     @Override
     public String getValue() {
-
-        if (parameters.isEmpty() && (defaultValue != null)) return defaultValue;
-
-        if (parameters.size() == 1) return parameters.get(0);
-
-        throw new RuntimeException("Parameter " + description
-                + " shall have exactly 1 argument.");
+        if (parameters.isEmpty() && defaultValue != null) {
+            return defaultValue;
+        }
+        if (parameters.size() == 1) {
+            return parameters.get(0);
+        }
+        throw new RuntimeException("Parameter '" + description
+                + "' must have exactly 1 argument.");
     }
 
+    /**
+     * Always returns {@code true} since any string is considered valid for this option.
+     */
     @Override
-    public boolean isValid(final java.lang.String value) {
+    public boolean isValid(final String value) {
         return true;
     }
-
 }
index 5b140bc..59c0230 100644 (file)
@@ -10,28 +10,37 @@ import eu.svjatoslav.commons.cli_helper.parameter_parser.Option;
 import java.util.List;
 
 /**
- * This class represents commandline option which accepts one or more parameters
- * which are strings.
+ * Represents a command-line option that accepts one or more string parameters.
  */
 public class StringOptions extends Option<List<String>, StringOptions> {
 
+    /**
+     * Creates a StringOptions object, requiring one or more string parameters.
+     *
+     * @param description a brief description of what these strings represent.
+     */
     public StringOptions(final String description) {
         super(description, ParameterCount.ONE_OR_MORE);
     }
 
     @Override
-    public java.lang.String describeFormat() {
+    public String describeFormat() {
         return "One to many string.";
     }
 
+    /**
+     * Returns the list of strings provided by the user.
+     */
     @Override
     public List<String> getValue() {
         return parameters;
     }
 
+    /**
+     * Always returns true since any string is valid for this option.
+     */
     @Override
-    public boolean isValid(final java.lang.String value) {
+    public boolean isValid(final String value) {
         return true;
     }
-
-}
+}
\ No newline at end of file