1 /*
2 AbstractOption.java
3 Creation date : 2/06/2010
4 Copyright © Benjamin Croizet (graffity2199@yahoo.fr)
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 or GNU Lesser General Public License as published by the
9 Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received copies of the GNU General Public License
18 and GNU Lesser General Public License along with this program;
19 if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 http://www.fsf.org/licensing/licenses/gpl.html
22 http://www.gnu.org/licenses/lgpl.html
23 */
24
25 package net.sourceforge.plantumldependency.commoncli.option;
26
27 import static java.util.logging.Level.SEVERE;
28 import static java.util.logging.Logger.getLogger;
29 import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.COMMA_CHAR;
30 import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.LINE_CHAR;
31 import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.SPACE_CHAR;
32 import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.TAB_CHAR;
33 import static net.sourceforge.plantumldependency.common.constants.log.ErrorConstants.UNEXPECTED_ERROR;
34 import static net.sourceforge.plantumldependency.common.utils.check.ParameterCheckerUtils.checkNull;
35 import static net.sourceforge.plantumldependency.commoncli.constants.log.ErrorConstants.FULL_USAGE_DESCRIPTION_NULL_ERROR;
36 import static net.sourceforge.plantumldependency.commoncli.constants.log.ErrorConstants.OPTION_NAME_NULL_ERROR;
37 import static net.sourceforge.plantumldependency.commoncli.constants.log.ErrorConstants.OPTION_SECONDARY_NAMES_NULL_ERROR;
38 import static net.sourceforge.plantumldependency.commoncli.constants.log.ErrorConstants.OPTION_STATUS_NULL_ERROR;
39
40 import java.util.Set;
41 import java.util.TreeSet;
42 import java.util.logging.Logger;
43
44 import net.sourceforge.plantumldependency.commoncli.option.status.OptionStatus;
45
46 /**
47 * The abstract implementation of the {@link Option} interface, providing common behaviors.
48 *
49 * @author Benjamin Croizet (<a href="mailto:graffity2199@yahoo.fr>graffity2199@yahoo.fr</a>)
50 * @since 1.3.0
51 * @version 1.3.0
52 */
53 public abstract class AbstractOption implements Option {
54
55 /** Serial version UID. */
56 private static final long serialVersionUID = -2714033818095664600L;
57
58 /** The class logger. */
59 private static final transient Logger LOGGER = getLogger(AbstractOption.class.getName());
60
61 /**
62 * The full option usage description, explaining what the option does (used for helping
63 * message).
64 */
65 private StringBuilder fullUsageDescription;
66
67 /** The option main name (for instance "-v" or "-o"). */
68 private String name;
69
70 /** The {@link Set} containing all option secondary names. */
71 private Set < String > secondaryNames;
72
73 /** The option status, telling if the option is active, inactive or hidden. */
74 private OptionStatus status;
75
76 /**
77 * Default constructor.
78 *
79 * @param optionName
80 * the option main name (for instance "-v" or "-o"), mustn't be <code>null</code>.
81 * @param optionSecondaryNames
82 * the {@link Set} containing all option secondary names, mustn't be
83 * <code>null</code> but may be empty. <i>Note : a new {@link Set} is created.</i>
84 * @param fullOptionDescription
85 * the full option usage description, explaining what the option does (used for
86 * helping message). <i>Note : a new {@link StringBuilder} is created.</i>
87 * @param optionStatus
88 * the option status, telling if the option is active, inactive or hidden, mustn't be
89 * <code>null</code>.
90 * @since 1.3.0
91 */
92 protected AbstractOption(final String optionName, final Set < String > optionSecondaryNames,
93 final StringBuilder fullOptionDescription, final OptionStatus optionStatus) {
94 setName(optionName);
95 setSecondaryNames(new TreeSet < String >(optionSecondaryNames));
96 setFullUsageDescription(new StringBuilder(fullOptionDescription));
97 setStatus(optionStatus);
98 }
99
100 /**
101 * {@inheritDoc}
102 *
103 * @since 1.3.0
104 */
105 @Override
106 public int compareTo(final Option o) {
107 return getName().compareTo(o.getName());
108 }
109
110 /**
111 * {@inheritDoc}
112 *
113 * @since 1.3.0
114 */
115 @Override
116 public Option deepClone() {
117 AbstractOption a = null;
118
119 try {
120 a = (AbstractOption) super.clone();
121 a.fullUsageDescription = new StringBuilder(getFullUsageDescription());
122 a.secondaryNames = new TreeSet < String >(getSecondaryNames());
123 } catch (final CloneNotSupportedException cnse) {
124 LOGGER.log(SEVERE, UNEXPECTED_ERROR, cnse);
125 }
126
127 return a;
128 }
129
130 /**
131 * {@inheritDoc}
132 *
133 * @since 1.3.0
134 */
135 @Override
136 public boolean equals(final Object obj) {
137 if (this == obj) {
138 return true;
139 }
140 if (obj == null) {
141 return false;
142 }
143 if (getClass() != obj.getClass()) {
144 return false;
145 }
146 final AbstractOption other = (AbstractOption) obj;
147 if (name == null) {
148 if (other.name != null) {
149 return false;
150 }
151 } else if (!name.equals(other.name)) {
152 return false;
153 }
154 return true;
155 }
156
157 /**
158 * {@inheritDoc}
159 *
160 * @since 1.3.0
161 */
162 @Override
163 public Set < String > getAllNames() {
164 final Set < String > allNames = new TreeSet < String >(getSecondaryNames());
165 allNames.add(getName());
166 return allNames;
167 }
168
169 /**
170 * {@inheritDoc}
171 *
172 * @since 1.3.0
173 */
174 @Override
175 public StringBuilder getFullUsage() {
176 final StringBuilder buffer = new StringBuilder(getName());
177
178 for (final String secondaryName : getSecondaryNames()) {
179 buffer.append(COMMA_CHAR);
180 buffer.append(SPACE_CHAR);
181 buffer.append(secondaryName);
182 }
183
184 buffer.append(getFullUsageAdditions());
185 buffer.append(LINE_CHAR);
186 buffer.append(TAB_CHAR);
187 buffer.append(TAB_CHAR);
188 buffer.append(getFullUsageDescription());
189 buffer.append(getFullUsageDescriptionAdditions());
190
191 return buffer;
192 }
193
194 /**
195 * Gets the full option usage additions, which can add additional information for the option
196 * synopsis information (if necessary, used for helping message).
197 *
198 * @return the full option usage additions.
199 * @since 1.3.0
200 */
201 protected abstract StringBuilder getFullUsageAdditions();
202
203 /**
204 * Gets the value of <code>fullUsageDescription</code>.
205 *
206 * @return the value of <code>fullUsageDescription</code>.
207 * @see #setFullUsageDescription(StringBuilder)
208 * @since 1.3.0
209 */
210 private StringBuilder getFullUsageDescription() {
211 return fullUsageDescription;
212 }
213
214 /**
215 * Gets the full option usage additions, which can add additional description explaining what
216 * the option does (if necessary, used for helping message).
217 *
218 * @return the full option usage additions.
219 * @since 1.3.0
220 */
221 protected abstract StringBuilder getFullUsageDescriptionAdditions();
222
223 /**
224 * {@inheritDoc}
225 *
226 * @since 1.3.0
227 */
228 @Override
229 public StringBuilder getMainUsage() {
230 final StringBuilder buffer = new StringBuilder(getName());
231 buffer.append(getMainUsageAdditions());
232 return buffer;
233 }
234
235 /**
236 * Gets the full option main usage additions, which can add additional information for the main
237 * option synopsis information (if necessary, used for helping message).
238 *
239 * @return the full option main usage additions.
240 * @since 1.3.0
241 */
242 protected abstract StringBuilder getMainUsageAdditions();
243
244 /**
245 * {@inheritDoc}
246 *
247 * @since 1.3.0
248 */
249 @Override
250 public String getName() {
251 return name;
252 }
253
254 /**
255 * {@inheritDoc}
256 *
257 * @since 1.3.0
258 */
259 @Override
260 public Set < String > getSecondaryNames() {
261 return secondaryNames;
262 }
263
264 /**
265 * Gets the value of <code>status</code>.
266 *
267 * @return the value of <code>status</code>.
268 * @since 1.3.0
269 */
270 @Override
271 public OptionStatus getStatus() {
272 return status;
273 }
274
275 /**
276 * {@inheritDoc}
277 *
278 * @since 1.3.0
279 */
280 @Override
281 public int hashCode() {
282 final int prime = 31;
283 int result = 1;
284 result = prime * result + ((name == null) ? 0 : name.hashCode());
285 return result;
286 }
287
288 /**
289 * {@inheritDoc}
290 *
291 * @since 1.3.0
292 */
293 @Override
294 public boolean isMandatory() {
295 return getStatus().isMandatory();
296 }
297
298 /**
299 * Sets the value of <code>fullUsageDescription</code>.
300 *
301 * @param value
302 * the <code>fullUsageDescription</code> to set, can be <code>null</code>.
303 * @see #getFullUsageDescription()
304 * @since 1.3.0
305 */
306 private void setFullUsageDescription(final StringBuilder value) {
307 checkNull(value, FULL_USAGE_DESCRIPTION_NULL_ERROR);
308
309 fullUsageDescription = value;
310 }
311
312 /**
313 * Sets the value of <code>name</code>.
314 *
315 * @param value
316 * the <code>name</code> to set, can be <code>null</code>.
317 * @see #getName()
318 * @since 1.3.0
319 */
320 private void setName(final String value) {
321 checkNull(value, OPTION_NAME_NULL_ERROR);
322
323 name = value;
324 }
325
326 /**
327 * Sets the value of <code>secondaryNames</code>.
328 *
329 * @param value
330 * the <code>secondaryNames</code> to set, can be <code>null</code>.
331 * @see #getSecondaryNames()
332 * @since 1.3.0
333 */
334 private void setSecondaryNames(final Set < String > value) {
335 checkNull(value, OPTION_SECONDARY_NAMES_NULL_ERROR);
336
337 secondaryNames = value;
338 }
339
340 /**
341 * Sets the value of <code>status</code>.
342 *
343 * @param value
344 * the <code>status</code> to set, can be <code>null</code>.
345 * @see #getStatus()
346 * @since 1.3.0
347 */
348 private void setStatus(final OptionStatus value) {
349 checkNull(value, OPTION_STATUS_NULL_ERROR);
350
351 status = value;
352 }
353
354 /**
355 * {@inheritDoc}
356 *
357 * @since 1.3.0
358 */
359 @Override
360 public String toString() {
361 return getClass().getSimpleName() + " [fullUsageDescription=" + fullUsageDescription + ", name=" + name
362 + ", secondaryNames=" + secondaryNames + ", status=" + status + "]";
363 }
364 }