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