001 /*
002 * Copyright 2008-2013 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2013 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.util.args;
022
023
024
025 import java.util.ArrayList;
026 import java.util.Arrays;
027 import java.util.Collections;
028 import java.util.Iterator;
029 import java.util.List;
030
031 import com.unboundid.util.Mutable;
032 import com.unboundid.util.ThreadSafety;
033 import com.unboundid.util.ThreadSafetyLevel;
034
035 import static com.unboundid.util.args.ArgsMessages.*;
036
037
038
039 /**
040 * This class defines an argument that is intended to hold one or more integer
041 * values. Integer arguments must take values. By default, any value will be
042 * allowed, but it is possible to restrict the set of values to a given range
043 * using upper and lower bounds.
044 */
045 @Mutable()
046 @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
047 public final class IntegerArgument
048 extends Argument
049 {
050 /**
051 * The serial version UID for this serializable class.
052 */
053 private static final long serialVersionUID = 3364985217337213643L;
054
055
056
057 // The set of values assigned to this argument.
058 private final ArrayList<Integer> values;
059
060 // The lower bound for this argument.
061 private final int lowerBound;
062
063 // The upper bound for this argument.
064 private final int upperBound;
065
066 // The list of default values that will be used if no values were provided.
067 private final List<Integer> defaultValues;
068
069
070
071 /**
072 * Creates a new integer argument with the provided information. There will
073 * not be any default values, nor will there be any restriction on values that
074 * may be assigned to this argument.
075 *
076 * @param shortIdentifier The short identifier for this argument. It may
077 * not be {@code null} if the long identifier is
078 * {@code null}.
079 * @param longIdentifier The long identifier for this argument. It may
080 * not be {@code null} if the short identifier is
081 * {@code null}.
082 * @param isRequired Indicates whether this argument is required to
083 * be provided.
084 * @param maxOccurrences The maximum number of times this argument may be
085 * provided on the command line. A value less than
086 * or equal to zero indicates that it may be present
087 * any number of times.
088 * @param valuePlaceholder A placeholder to display in usage information to
089 * indicate that a value must be provided. It must
090 * not be {@code null}.
091 * @param description A human-readable description for this argument.
092 * It must not be {@code null}.
093 *
094 * @throws ArgumentException If there is a problem with the definition of
095 * this argument.
096 */
097 public IntegerArgument(final Character shortIdentifier,
098 final String longIdentifier, final boolean isRequired,
099 final int maxOccurrences,
100 final String valuePlaceholder,
101 final String description)
102 throws ArgumentException
103 {
104 this(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
105 valuePlaceholder, description, Integer.MIN_VALUE, Integer.MAX_VALUE,
106 (List<Integer>) null);
107 }
108
109
110
111 /**
112 * Creates a new integer argument with the provided information. There will
113 * not be any default values, but the range of values that will be allowed may
114 * be restricted.
115 *
116 * @param shortIdentifier The short identifier for this argument. It may
117 * not be {@code null} if the long identifier is
118 * {@code null}.
119 * @param longIdentifier The long identifier for this argument. It may
120 * not be {@code null} if the short identifier is
121 * {@code null}.
122 * @param isRequired Indicates whether this argument is required to
123 * be provided.
124 * @param maxOccurrences The maximum number of times this argument may be
125 * provided on the command line. A value less than
126 * or equal to zero indicates that it may be present
127 * any number of times.
128 * @param valuePlaceholder A placeholder to display in usage information to
129 * indicate that a value must be provided. It must
130 * not be {@code null}.
131 * @param description A human-readable description for this argument.
132 * It must not be {@code null}.
133 * @param lowerBound The smallest value that this argument is allowed
134 * to have. It should be {@code Integer.MIN_VALUE}
135 * if there should be no lower bound.
136 * @param upperBound The largest value that this argument is allowed
137 * to have. It should be {@code Integer.MAX_VALUE}
138 * if there should be no upper bound.
139 *
140 * @throws ArgumentException If there is a problem with the definition of
141 * this argument.
142 */
143 public IntegerArgument(final Character shortIdentifier,
144 final String longIdentifier, final boolean isRequired,
145 final int maxOccurrences,
146 final String valuePlaceholder,
147 final String description,
148 final int lowerBound, final int upperBound)
149 throws ArgumentException
150 {
151 this(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
152 valuePlaceholder, description, lowerBound, upperBound,
153 (List<Integer>) null);
154 }
155
156
157
158 /**
159 * Creates a new integer argument with the provided information. There will
160 * not be any restriction on values that may be assigned to this argument.
161 *
162 * @param shortIdentifier The short identifier for this argument. It may
163 * not be {@code null} if the long identifier is
164 * {@code null}.
165 * @param longIdentifier The long identifier for this argument. It may
166 * not be {@code null} if the short identifier is
167 * {@code null}.
168 * @param isRequired Indicates whether this argument is required to
169 * be provided.
170 * @param maxOccurrences The maximum number of times this argument may be
171 * provided on the command line. A value less than
172 * or equal to zero indicates that it may be present
173 * any number of times.
174 * @param valuePlaceholder A placeholder to display in usage information to
175 * indicate that a value must be provided. It must
176 * not be {@code null}.
177 * @param description A human-readable description for this argument.
178 * It must not be {@code null}.
179 * @param defaultValue The default value that will be used for this
180 * argument if no values are provided. It may be
181 * {@code null} if there should not be a default
182 * value.
183 *
184 * @throws ArgumentException If there is a problem with the definition of
185 * this argument.
186 */
187 public IntegerArgument(final Character shortIdentifier,
188 final String longIdentifier, final boolean isRequired,
189 final int maxOccurrences,
190 final String valuePlaceholder,
191 final String description,
192 final Integer defaultValue)
193 throws ArgumentException
194 {
195 this(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
196 valuePlaceholder, description, Integer.MIN_VALUE, Integer.MAX_VALUE,
197 ((defaultValue == null) ? null : Arrays.asList(defaultValue)));
198 }
199
200
201
202 /**
203 * Creates a new integer argument with the provided information. There will
204 * not be any restriction on values that may be assigned to this argument.
205 *
206 * @param shortIdentifier The short identifier for this argument. It may
207 * not be {@code null} if the long identifier is
208 * {@code null}.
209 * @param longIdentifier The long identifier for this argument. It may
210 * not be {@code null} if the short identifier is
211 * {@code null}.
212 * @param isRequired Indicates whether this argument is required to
213 * be provided.
214 * @param maxOccurrences The maximum number of times this argument may be
215 * provided on the command line. A value less than
216 * or equal to zero indicates that it may be present
217 * any number of times.
218 * @param valuePlaceholder A placeholder to display in usage information to
219 * indicate that a value must be provided. It must
220 * not be {@code null}.
221 * @param description A human-readable description for this argument.
222 * It must not be {@code null}.
223 * @param defaultValues The set of default values that will be used for
224 * this argument if no values are provided.
225 *
226 * @throws ArgumentException If there is a problem with the definition of
227 * this argument.
228 */
229 public IntegerArgument(final Character shortIdentifier,
230 final String longIdentifier, final boolean isRequired,
231 final int maxOccurrences,
232 final String valuePlaceholder,
233 final String description,
234 final List<Integer> defaultValues)
235 throws ArgumentException
236 {
237 this(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
238 valuePlaceholder, description, Integer.MIN_VALUE, Integer.MAX_VALUE,
239 defaultValues);
240 }
241
242
243
244 /**
245 * Creates a new integer argument with the provided information.
246 *
247 * @param shortIdentifier The short identifier for this argument. It may
248 * not be {@code null} if the long identifier is
249 * {@code null}.
250 * @param longIdentifier The long identifier for this argument. It may
251 * not be {@code null} if the short identifier is
252 * {@code null}.
253 * @param isRequired Indicates whether this argument is required to
254 * be provided.
255 * @param maxOccurrences The maximum number of times this argument may be
256 * provided on the command line. A value less than
257 * or equal to zero indicates that it may be present
258 * any number of times.
259 * @param valuePlaceholder A placeholder to display in usage information to
260 * indicate that a value must be provided. It must
261 * not be {@code null}.
262 * @param description A human-readable description for this argument.
263 * It must not be {@code null}.
264 * @param lowerBound The smallest value that this argument is allowed
265 * to have. It should be {@code Integer.MIN_VALUE}
266 * if there should be no lower bound.
267 * @param upperBound The largest value that this argument is allowed
268 * to have. It should be {@code Integer.MAX_VALUE}
269 * if there should be no upper bound.
270 * @param defaultValue The default value that will be used for this
271 * argument if no values are provided. It may be
272 * {@code null} if there should not be a default
273 * value.
274 *
275 * @throws ArgumentException If there is a problem with the definition of
276 * this argument.
277 */
278 public IntegerArgument(final Character shortIdentifier,
279 final String longIdentifier, final boolean isRequired,
280 final int maxOccurrences,
281 final String valuePlaceholder,
282 final String description, final int lowerBound,
283 final int upperBound,
284 final Integer defaultValue)
285 throws ArgumentException
286 {
287 this(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
288 valuePlaceholder, description, lowerBound, upperBound,
289 ((defaultValue == null) ? null : Arrays.asList(defaultValue)));
290 }
291
292
293
294 /**
295 * Creates a new integer argument with the provided information.
296 *
297 * @param shortIdentifier The short identifier for this argument. It may
298 * not be {@code null} if the long identifier is
299 * {@code null}.
300 * @param longIdentifier The long identifier for this argument. It may
301 * not be {@code null} if the short identifier is
302 * {@code null}.
303 * @param isRequired Indicates whether this argument is required to
304 * be provided.
305 * @param maxOccurrences The maximum number of times this argument may be
306 * provided on the command line. A value less than
307 * or equal to zero indicates that it may be present
308 * any number of times.
309 * @param valuePlaceholder A placeholder to display in usage information to
310 * indicate that a value must be provided. It must
311 * not be {@code null}.
312 * @param description A human-readable description for this argument.
313 * It must not be {@code null}.
314 * @param lowerBound The smallest value that this argument is allowed
315 * to have. It should be {@code Integer.MIN_VALUE}
316 * if there should be no lower bound.
317 * @param upperBound The largest value that this argument is allowed
318 * to have. It should be {@code Integer.MAX_VALUE}
319 * if there should be no upper bound.
320 * @param defaultValues The set of default values that will be used for
321 * this argument if no values are provided.
322 *
323 * @throws ArgumentException If there is a problem with the definition of
324 * this argument.
325 */
326 public IntegerArgument(final Character shortIdentifier,
327 final String longIdentifier, final boolean isRequired,
328 final int maxOccurrences,
329 final String valuePlaceholder,
330 final String description, final int lowerBound,
331 final int upperBound,
332 final List<Integer> defaultValues)
333 throws ArgumentException
334 {
335 super(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
336 valuePlaceholder, description);
337
338 if (valuePlaceholder == null)
339 {
340 throw new ArgumentException(ERR_ARG_MUST_TAKE_VALUE.get(
341 getIdentifierString()));
342 }
343
344 this.lowerBound = lowerBound;
345 this.upperBound = upperBound;
346
347 if ((defaultValues == null) || defaultValues.isEmpty())
348 {
349 this.defaultValues = null;
350 }
351 else
352 {
353 this.defaultValues = Collections.unmodifiableList(defaultValues);
354 }
355
356 values = new ArrayList<Integer>();
357 }
358
359
360
361 /**
362 * Creates a new integer argument that is a "clean" copy of the provided
363 * source argument.
364 *
365 * @param source The source argument to use for this argument.
366 */
367 private IntegerArgument(final IntegerArgument source)
368 {
369 super(source);
370
371 lowerBound = source.lowerBound;
372 upperBound = source.upperBound;
373 defaultValues = source.defaultValues;
374 values = new ArrayList<Integer>();
375 }
376
377
378
379 /**
380 * Retrieves the smallest value that this argument will be allowed to have.
381 *
382 * @return The smallest value that this argument will be allowed to have.
383 */
384 public int getLowerBound()
385 {
386 return lowerBound;
387 }
388
389
390
391 /**
392 * Retrieves the largest value that this argument will be allowed to have.
393 *
394 * @return The largest value that this argument will be allowed to have.
395 */
396 public int getUpperBound()
397 {
398 return upperBound;
399 }
400
401
402
403 /**
404 * Retrieves the list of default values for this argument, which will be used
405 * if no values were provided.
406 *
407 * @return The list of default values for this argument, or {@code null} if
408 * there are no default values.
409 */
410 public List<Integer> getDefaultValues()
411 {
412 return defaultValues;
413 }
414
415
416
417 /**
418 * {@inheritDoc}
419 */
420 @Override()
421 protected void addValue(final String valueString)
422 throws ArgumentException
423 {
424 final int intValue;
425 try
426 {
427 intValue = Integer.parseInt(valueString);
428 }
429 catch (Exception e)
430 {
431 throw new ArgumentException(ERR_INTEGER_VALUE_NOT_INT.get(valueString,
432 getIdentifierString()), e);
433 }
434
435 if (intValue < lowerBound)
436 {
437 throw new ArgumentException(ERR_INTEGER_VALUE_BELOW_LOWER_BOUND.get(
438 intValue, getIdentifierString(),
439 lowerBound));
440 }
441
442 if (intValue > upperBound)
443 {
444 throw new ArgumentException(ERR_INTEGER_VALUE_ABOVE_UPPER_BOUND.get(
445 intValue, getIdentifierString(),
446 upperBound));
447 }
448
449 if (values.size() >= getMaxOccurrences())
450 {
451 throw new ArgumentException(ERR_ARG_MAX_OCCURRENCES_EXCEEDED.get(
452 getIdentifierString()));
453 }
454
455 values.add(intValue);
456 }
457
458
459
460 /**
461 * Retrieves the value for this argument, or the default value if none was
462 * provided. If this argument has multiple values, then the first will be
463 * returned.
464 *
465 * @return The value for this argument, or the default value if none was
466 * provided, or {@code null} if it does not have any values or
467 * default values.
468 */
469 public Integer getValue()
470 {
471 if (values.isEmpty())
472 {
473 if ((defaultValues == null) || defaultValues.isEmpty())
474 {
475 return null;
476 }
477 else
478 {
479 return defaultValues.get(0);
480 }
481 }
482
483 return values.get(0);
484 }
485
486
487
488 /**
489 * Retrieves the set of values for this argument, or the default values if
490 * none were provided.
491 *
492 * @return The set of values for this argument, or the default values if none
493 * were provided.
494 */
495 public List<Integer> getValues()
496 {
497 if (values.isEmpty() && (defaultValues != null))
498 {
499 return defaultValues;
500 }
501
502 return Collections.unmodifiableList(values);
503 }
504
505
506
507 /**
508 * {@inheritDoc}
509 */
510 @Override()
511 protected boolean hasDefaultValue()
512 {
513 return ((defaultValues != null) && (! defaultValues.isEmpty()));
514 }
515
516
517
518 /**
519 * {@inheritDoc}
520 */
521 @Override()
522 public String getDataTypeName()
523 {
524 return INFO_INTEGER_TYPE_NAME.get();
525 }
526
527
528
529 /**
530 * {@inheritDoc}
531 */
532 @Override()
533 public String getValueConstraints()
534 {
535 return INFO_INTEGER_CONSTRAINTS_LOWER_AND_UPPER_BOUND.get(lowerBound,
536 upperBound);
537 }
538
539
540
541 /**
542 * {@inheritDoc}
543 */
544 @Override()
545 public IntegerArgument getCleanCopy()
546 {
547 return new IntegerArgument(this);
548 }
549
550
551
552 /**
553 * {@inheritDoc}
554 */
555 @Override()
556 public void toString(final StringBuilder buffer)
557 {
558 buffer.append("IntegerArgument(");
559 appendBasicToStringInfo(buffer);
560
561 buffer.append(", lowerBound=");
562 buffer.append(lowerBound);
563 buffer.append(", upperBound=");
564 buffer.append(upperBound);
565
566 if ((defaultValues != null) && (! defaultValues.isEmpty()))
567 {
568 if (defaultValues.size() == 1)
569 {
570 buffer.append(", defaultValue='");
571 buffer.append(defaultValues.get(0).toString());
572 }
573 else
574 {
575 buffer.append(", defaultValues={");
576
577 final Iterator<Integer> iterator = defaultValues.iterator();
578 while (iterator.hasNext())
579 {
580 buffer.append('\'');
581 buffer.append(iterator.next().toString());
582 buffer.append('\'');
583
584 if (iterator.hasNext())
585 {
586 buffer.append(", ");
587 }
588 }
589
590 buffer.append('}');
591 }
592 }
593
594 buffer.append(')');
595 }
596 }