9bcea3f1380f27acbfcfa75633a543f12521acc9
[cli-helper.git] / src / main / java / eu / svjatoslav / commons / cli_helper / parameter_parser / Option.java
1 /*
2  * Svjatoslav Commons - shared library of common functionality. Author: Svjatoslav Agejenko.
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.commons.cli_helper.parameter_parser;
6
7 import java.util.ArrayList;
8 import java.util.List;
9
10 import static eu.svjatoslav.commons.cli_helper.parameter_parser.ParameterCount.NONE;
11 import static java.lang.String.join;
12 import static java.util.Collections.addAll;
13 import static java.util.stream.Collectors.joining;
14
15 public abstract class Option<T, I extends Option> {
16
17     /**
18      * Purpose of this option, like: input image path, compression level, etc...
19      *
20      * Note: for describing option type there is {@link #describeFormat()}.
21      */
22     public final String description;
23
24     /**
25      * List of arguments for this parameter.
26      */
27     public final List<String> parameters = new ArrayList<>();
28     final ParameterCount parameterCount;
29
30     /**
31      * List of aliases for this option.
32      */
33     private final List<String> aliases = new ArrayList<>();
34
35     /**
36      * Indicates that at least one parameter is mandatory for this option.
37      */
38     protected boolean mandatory;
39
40     /**
41      * If this parameter was present in the commandline, then this boolean will
42      * be set to <code>true</code>.
43      */
44     private boolean isPresent;
45
46     public Option(final boolean mandatory,
47                   final ParameterCount parameterCount, final String description,
48                   final String... aliases2) {
49
50         this.mandatory = mandatory;
51         this.description = description;
52         this.parameterCount = parameterCount;
53
54         // save aliases
55         addAll(aliases, aliases2);
56     }
57
58     public Option(final String description, final ParameterCount parameterCount) {
59         this.description = description;
60         this.parameterCount = parameterCount;
61     }
62
63     @SuppressWarnings("unchecked")
64     public I addAliases(final String... aliasArray) {
65
66         // save aliases
67         addAll(aliases, aliasArray);
68
69         return (I) this;
70     }
71
72     /**
73      * @param parameterString parameter to add
74      * @return <code>true</code> if no errors were found. <code>false</code>
75      * otherwise.
76      */
77     public boolean addParameter(final String parameterString) {
78         // check if arguments are allowed for this parameter
79         if (parameterCount.equals(NONE)) {
80             System.out
81                     .println("Error! No parameters are allowed for option(s): "
82                             + getAliasesAsString());
83             return false;
84         }
85
86         // check if multiple arguments are allowed
87         if ((!parameters.isEmpty())
88                 && (parameterCount.equals(ParameterCount.ONE))) {
89             System.out
90                     .println("Error! Only single parameter is allowed for argument(s): "
91                             + getAliasesAsString());
92             return false;
93         }
94
95         if (isValid(parameterString)) {
96             parameters.add(parameterString);
97             return true;
98         } else {
99             System.out.println("Error! Invalid parameter type for \"" + parameterString
100                     + "\". It shall be " + describeFormat() + ".");
101             return false;
102         }
103     }
104
105     /**
106      * @return Single line parameter type description. For example: "file", "date", "integer", "regular expression", etc..
107      * <p>
108      * Note: for argument purpose description there is {@link #description}
109      */
110     public abstract String describeFormat();
111
112     /**
113      * @return aliases for this parameter as string.
114      */
115     public String getAliasesAsString() {
116         return join(", ", aliases);
117     }
118
119     /**
120      * @return help for this option.
121      */
122     public String getHelp() {
123         final StringBuilder result = new StringBuilder();
124
125         // first line
126         result.append(getAliasesAsString());
127         if (!NONE.equals(parameterCount)) {
128             result
129                     .append(" (")
130                     .append(isMandatory() ? "mandatory, " : "")
131                     .append(describeFormat())
132                     .append(")");
133
134             if (parameterCount.equals(ParameterCount.ONE_OR_MORE))
135                 result.append("...");
136         }
137         result.append("\n");
138
139         // second line
140         result.append("    " + description + "\n");
141
142         return result.toString();
143     }
144
145     public abstract T getValue();
146
147     public boolean isMandatory() {
148         return mandatory;
149     }
150
151     /**
152      * @return the parameterSpecified
153      */
154     public boolean isPresent() {
155         return isPresent;
156     }
157
158     /**
159      * @param present the parameterSpecified to set
160      */
161     protected void setPresent(final boolean present) {
162         this.isPresent = present;
163     }
164
165     /**
166      * @param alias alias to check against
167      * @return <code>true</code> if given alias is registered for this
168      * parameter.
169      */
170     public boolean matchesAlias(final String alias) {
171         return aliases.contains(alias);
172
173     }
174
175     /**
176      * Notifies this option that no more parameters will follow.
177      * This gives option chance to verify if this is ok.
178      *
179      * @return <code>true</code> if no errors were found. <code>false</code>
180      * otherwise.
181      */
182     public boolean noMoreArguments() {
183
184         if ((!parameterCount.equals(NONE))
185                 && (parameters.isEmpty())) {
186
187             System.out.println("Error! " + getAliasesAsString()
188                     + " require at least one parameter.");
189
190             return false;
191         }
192         return true;
193     }
194
195     @SuppressWarnings("unchecked")
196     public I setMandatory() {
197         mandatory = true;
198         return (I) this;
199     }
200
201     /**
202      * @param value value to validate
203      * @return <code>true</code> if value is correct, <code>false</code>
204      * otherwise.
205      */
206     public abstract boolean isValid(String value);
207
208 }