Added FileParameters type.
[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-2017, 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     public final String description;
19     public final List<String> arguments = new ArrayList<>();
20     final ArgumentCount argumentCount;
21     private final List<String> aliases = new ArrayList<>();
22     /**
23      * Indicates that at least one argument is mandatory for this parameter.
24      */
25     protected boolean mandatory;
26     /**
27      * If this parameter was present in the commandline, then this boolean will
28      * be set to <code>true</code>.
29      */
30     private boolean specified;
31
32     public Parameter(final boolean mandatory,
33                      final ArgumentCount argumentCount, final String description,
34                      final String... aliases2) {
35
36         this.mandatory = mandatory;
37         this.description = description;
38         this.argumentCount = argumentCount;
39
40         // save aliases
41         Collections.addAll(aliases, aliases2);
42
43     }
44
45     public Parameter(final String description, final ArgumentCount argumentCount) {
46         this.description = description;
47         this.argumentCount = argumentCount;
48     }
49
50     @SuppressWarnings("unchecked")
51     public I addAliases(final String... aliasArray) {
52
53         // save aliases
54         Collections.addAll(aliases, aliasArray);
55
56         return (I) this;
57     }
58
59     /**
60      * @param argumentString argument to add
61      * @return <code>true</code> if no errors were found. <code>false</code>
62      * otherwise.
63      */
64     public boolean addArgument(final String argumentString) {
65         // check if arguments are allowed for this parameter
66         if (argumentCount.equals(ArgumentCount.NONE)) {
67             System.out
68                     .println("Error! No arguments are allowed for parameters: "
69                             + getAliases());
70             return false;
71         }
72
73         // check if multiple arguments are allowed
74         if ((arguments.size() > 0)
75                 && (argumentCount.equals(ArgumentCount.SINGLE))) {
76             System.out
77                     .println("Error! Only single argument is allowed for parameters: "
78                             + getAliases());
79             return false;
80         }
81
82         if (!validate(argumentString)) {
83
84             System.out.println("Error! Invalid argument \"" + argumentString
85                     + "\". It shall be " + describeFormat() + ".");
86             return false;
87
88         }
89
90         arguments.add(argumentString);
91
92         return true;
93     }
94
95     /**
96      * @return Single line argument type description.
97      */
98     public abstract String describeFormat();
99
100     public String getAliases() {
101         final StringBuilder buffer = new StringBuilder();
102
103         for (final String alias : aliases) {
104
105             if (buffer.length() > 0)
106                 buffer.append(", ");
107
108             buffer.append(alias);
109         }
110
111         return buffer.toString();
112     }
113
114     public String getHelp() {
115         final StringBuilder buffer = new StringBuilder();
116
117         // first line
118         buffer.append(getAliases());
119         if (!argumentCount.equals(ArgumentCount.NONE)) {
120             buffer
121                     .append(" (")
122                     .append(isMandatory() ? "mandatory, " : "")
123                     .append(describeFormat())
124                     .append(")");
125
126             if (argumentCount.equals(ArgumentCount.MULTI))
127                 buffer.append("...");
128         }
129         buffer.append("\n");
130
131         // second line
132         buffer.append("    " + description + "\n");
133
134         return buffer.toString();
135     }
136
137     public abstract T getValue();
138
139     public boolean isMandatory() {
140         return mandatory;
141     }
142
143     /**
144      * @return the parameterSpecified
145      */
146     public boolean isSpecified() {
147         return specified;
148     }
149
150     /**
151      * @param specified the parameterSpecified to set
152      */
153     protected void setSpecified(final boolean specified) {
154         this.specified = specified;
155     }
156
157     /**
158      * @param alias alias to check against
159      * @return <code>true</code> if given alias is registered for this
160      * parameter.
161      */
162     public boolean matchesAlias(final String alias) {
163         return aliases.contains(alias);
164
165     }
166
167     /**
168      * Notifies this parameter that no more arguments will follow. This gives
169      * parameter chance to verify if this is ok.
170      *
171      * @return <code>true</code> if no errors were found. <code>false</code>
172      * otherwise.
173      */
174     public boolean noMoreArguments() {
175
176         if ((!argumentCount.equals(ArgumentCount.NONE))
177                 && (arguments.isEmpty())) {
178
179             System.out.println("Error! " + getAliases()
180                     + " require at least one following argument.");
181
182             return false;
183         }
184         return true;
185     }
186
187     @SuppressWarnings("unchecked")
188     public I setMandatory() {
189         mandatory = true;
190         return (I) this;
191     }
192
193     /**
194      * @param value value to validate
195      * @return <code>true</code> if value is correct, <code>false</code>
196      * otherwise.
197      */
198     public abstract boolean validate(String value);
199
200 }