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