--- /dev/null
+/*
+ * 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;
+
+import java.util.ArrayList;
+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;
+
+public abstract class Option<T, I extends Option> {
+
+ /**
+ * Purpose of this option, like: input image path, compression level, etc...
+ *
+ * Note: for describing option type there is {@link #describeFormat()}.
+ */
+ public final String description;
+
+ /**
+ * List of arguments for this parameter.
+ */
+ public final List<String> parameters = new ArrayList<>();
+ final ParameterCount parameterCount;
+
+ /**
+ * List of aliases for this option.
+ */
+ private final List<String> aliases = new ArrayList<>();
+
+ /**
+ * Indicates that at least one parameter is mandatory for this option.
+ */
+ protected boolean mandatory;
+
+ /**
+ * If this parameter was present in the commandline, then this boolean will
+ * be set to <code>true</code>.
+ */
+ private boolean isPresent;
+
+ public Option(final boolean mandatory,
+ 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;
+ }
+
+ @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.
+ */
+ public boolean addParameter(final String parameterString) {
+ // check if arguments are allowed for this parameter
+ if (parameterCount.equals(NONE)) {
+ 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.SINGLE))) {
+ System.out
+ .println("Error! Only single parameter is allowed for argument(s): "
+ + getAliasesAsString());
+ return false;
+ }
+
+ if (isValid(parameterString)) {
+ parameters.add(parameterString);
+ return true;
+ } else {
+ System.out.println("Error! Invalid parameter type for \"" + parameterString
+ + "\". It shall 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}
+ */
+ public abstract String describeFormat();
+
+ /**
+ * @return aliases for this parameter as string.
+ */
+ public String getAliasesAsString() {
+ return join(", ", aliases);
+ }
+
+ /**
+ * @return help for this option.
+ */
+ public String getHelp() {
+ final StringBuilder result = new StringBuilder();
+
+ // first line
+ result.append(getAliasesAsString());
+ if (!NONE.equals(parameterCount)) {
+ result
+ .append(" (")
+ .append(isMandatory() ? "mandatory, " : "")
+ .append(describeFormat())
+ .append(")");
+
+ if (parameterCount.equals(ParameterCount.MULTI))
+ result.append("...");
+ }
+ result.append("\n");
+
+ // second line
+ result.append(" " + description + "\n");
+
+ return result.toString();
+ }
+
+ public abstract T getValue();
+
+ public boolean isMandatory() {
+ return mandatory;
+ }
+
+ /**
+ * @return the parameterSpecified
+ */
+ public boolean isPresent() {
+ return isPresent;
+ }
+
+ /**
+ * @param present the parameterSpecified to set
+ */
+ 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.
+ */
+ 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.
+ *
+ * @return <code>true</code> if no errors were found. <code>false</code>
+ * otherwise.
+ */
+ public boolean noMoreArguments() {
+
+ if ((!parameterCount.equals(NONE))
+ && (parameters.isEmpty())) {
+
+ System.out.println("Error! " + getAliasesAsString()
+ + " require at least one parameter.");
+
+ return false;
+ }
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ public I setMandatory() {
+ mandatory = true;
+ return (I) this;
+ }
+
+ /**
+ * @param value value to validate
+ * @return <code>true</code> if value is correct, <code>false</code>
+ * otherwise.
+ */
+ public abstract boolean isValid(String value);
+
+}