Update naming in commandline parser
[cli-helper.git] / src / main / java / eu / svjatoslav / commons / cli_helper / parameter_parser / Option.java
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
new file mode 100755 (executable)
index 0000000..cb36966
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * 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);
+
+}