From 77449eb0bf3171b7e564bd84628dfce29fa0c407 Mon Sep 17 00:00:00 2001 From: Svjatoslav Agejenko Date: Thu, 20 Mar 2025 23:19:01 +0200 Subject: [PATCH] Better documentation and bugfix --- .../cli_helper/parameter_parser/Option.java | 203 +++++++++--------- .../parameter_parser/ParameterCount.java | 18 +- .../cli_helper/parameter_parser/Parser.java | 139 ++++++++---- .../parameter/DirectoryOption.java | 79 +++---- .../parameter/DirectoryOptions.java | 70 +++--- .../parameter/ExistenceType.java | 22 +- .../parameter/FileOption.java | 97 +++++---- .../parameter/FileOptions.java | 46 ++-- .../parameter/FloatOption.java | 72 +++++-- .../parameter/IntegerOption.java | 35 ++- .../parameter/NullOption.java | 28 ++- .../parameter/StringOption.java | 52 +++-- .../parameter/StringOptions.java | 21 +- 13 files changed, 511 insertions(+), 371 deletions(-) diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Option.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Option.java index d591663..eb33fa7 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Option.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Option.java @@ -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: + * * - * @param type of value that this option returns. - * @param type of this option. + * @param the type of object returned by {@link #getValue()} + * @param the actual subclass type, used to enable fluent method chaining */ -public abstract class Option { +public abstract class Option> { /** - * 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 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 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 true. - */ - 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 true if no errors were found. false - * 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.. - *

- * 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() ? "" : 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 true 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 true if this parameter is present in the command line, - * false 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 true 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 true if no errors were found. false - * 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 true if value is correct, false - * 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); - } diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/ParameterCount.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/ParameterCount.java index 0d74b3f..1a30fe8 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/ParameterCount.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/ParameterCount.java @@ -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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Parser.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Parser.java index d307ea3..41c6b40 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Parser.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/Parser.java @@ -5,91 +5,136 @@ 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. + *

+ * Usage: + *

{@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();
+ * }
*/ public class Parser { - private final ArrayList> options = new ArrayList<>(); - - public E add(final E parameter) { - options.add(parameter); - return parameter; - } + private final List>> options = new ArrayList<>(); /** - * @return true if no errors were found. false - * otherwise. + * Registers an option with this parser. + * + * @param option the option to be added + * @param 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 add(final E option) { + options.add(option); + return option; } /** - * Return parameter by given alias or null if no parameter - * exists for given alias. + * Looks up an option by alias. * - * @param alias parameter alias - * @return found parameter or null 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 true if no errors were found. false - * 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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOption.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOption.java index ee52751..63c1714 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOption.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOption.java @@ -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 { - /** - * 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 { } /** - * 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 { } /** - * 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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOptions.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOptions.java index d012cf9..fb0d923 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOptions.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/DirectoryOptions.java @@ -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, DirectoryOptions> { - /** - * This enum is used to define if resource denoted by particular option parameter shall exist or not. - *

- * 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 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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/ExistenceType.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/ExistenceType.java index e001b0d..a3cccc1 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/ExistenceType.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/ExistenceType.java @@ -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. - *

- * 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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOption.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOption.java index c10ec1e..00c295d 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOption.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOption.java @@ -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 { + /** 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 { } /** - * 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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOptions.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOptions.java index 9534224..2d0e8ab 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOptions.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FileOptions.java @@ -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, 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 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, 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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FloatOption.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FloatOption.java index 1ab5ec4..8aaca36 100644 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FloatOption.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/FloatOption.java @@ -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 { - 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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/IntegerOption.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/IntegerOption.java index 592ab00..3fd6ead 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/IntegerOption.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/IntegerOption.java @@ -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 { + /** + * 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; diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/NullOption.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/NullOption.java index 9b5ad88..cdf6583 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/NullOption.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/NullOption.java @@ -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 { + /** + * 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 diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOption.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOption.java index d7cb3e7..fa7f102 100755 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOption.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOption.java @@ -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 { + /** + * 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; } - } diff --git a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOptions.java b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOptions.java index 5b140bc..59c0230 100644 --- a/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOptions.java +++ b/src/main/java/eu/svjatoslav/commons/cli_helper/parameter_parser/parameter/StringOptions.java @@ -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, 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 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 -- 2.20.1