001/*
002 * Copyright 2010-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2010-2019 Ping Identity Corporation
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 */
021package com.unboundid.util.args;
022
023
024
025import java.util.Collections;
026import java.util.List;
027
028import com.unboundid.util.Mutable;
029import com.unboundid.util.StaticUtils;
030import com.unboundid.util.ThreadSafety;
031import com.unboundid.util.ThreadSafetyLevel;
032
033import static com.unboundid.util.args.ArgsMessages.*;
034
035
036
037/**
038 * Creates a new argument that is intended to represent Boolean states based on
039 * the value provided for this argument.  This is similar to the
040 * {@link BooleanArgument} argument type, except that the Boolean value for this
041 * argument must be explicitly specified, whereas the Boolean value for the
042 * {@code BooleanArgument} class is inferred based on whether the argument
043 * was present.
044 * <BR><BR>
045 * Arguments of this type must always have exactly one value.  Values of "true",
046 * "t", "yes", "y", "on", and "1" will be interpreted as representing a Boolean
047 * value of {@code true}, and values of "false", "f", "no", "n", "off", and "0"
048 * will be interpreted as representing a Boolean value of {@code false}.  No
049 * other values will be allowed.
050 */
051@Mutable()
052@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
053public final class BooleanValueArgument
054       extends Argument
055{
056  /**
057   * The serial version UID for this serializable class.
058   */
059  private static final long serialVersionUID = -3903872574065550222L;
060
061
062
063  // The default value for this argument.
064  private final Boolean defaultValue;
065
066  // The provided value for this argument.
067  private Boolean value;
068
069
070
071  /**
072   * Creates a new Boolean value argument with the provided information.  It
073   * will not be required, will use a default value placeholder, and will not
074   * have a default value.
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  description       A human-readable description for this argument.
083   *                           It must not be {@code null}.
084   *
085   * @throws  ArgumentException  If there is a problem with the definition of
086   *                             this argument.
087   */
088  public BooleanValueArgument(final Character shortIdentifier,
089                              final String longIdentifier,
090                              final String description)
091         throws ArgumentException
092  {
093    this(shortIdentifier, longIdentifier, false, null, description);
094  }
095
096
097
098  /**
099   * Creates a new Boolean value argument with no default value.
100   *
101   * @param  shortIdentifier   The short identifier for this argument.  It may
102   *                           not be {@code null} if the long identifier is
103   *                           {@code null}.
104   * @param  longIdentifier    The long identifier for this argument.  It may
105   *                           not be {@code null} if the short identifier is
106   *                           {@code null}.
107   * @param  isRequired        Indicates whether this argument is required to
108   *                           be provided.
109   * @param  valuePlaceholder  A placeholder to display in usage information to
110   *                           indicate that a value must be provided.  It may
111   *                           be {@code null} if a default placeholder should
112   *                           be used.
113   * @param  description       A human-readable description for this argument.
114   *                           It must not be {@code null}.
115   *
116   * @throws  ArgumentException  If there is a problem with the definition of
117   *                             this argument.
118   */
119  public BooleanValueArgument(final Character shortIdentifier,
120                              final String longIdentifier,
121                              final boolean isRequired,
122                              final String valuePlaceholder,
123                              final String description)
124         throws ArgumentException
125  {
126    this(shortIdentifier, longIdentifier, isRequired, valuePlaceholder,
127         description, null);
128  }
129
130
131
132  /**
133   * Creates a new Boolean value argument with the specified default value.
134   *
135   * @param  shortIdentifier   The short identifier for this argument.  It may
136   *                           not be {@code null} if the long identifier is
137   *                           {@code null}.
138   * @param  longIdentifier    The long identifier for this argument.  It may
139   *                           not be {@code null} if the short identifier is
140   *                           {@code null}.
141   * @param  isRequired        Indicates whether this argument is required to
142   *                           be provided.
143   * @param  valuePlaceholder  A placeholder to display in usage information to
144   *                           indicate that a value must be provided.  It may
145   *                           be {@code null} if a default placeholder should
146   *                           be used.
147   * @param  description       A human-readable description for this argument.
148   *                           It must not be {@code null}.
149   * @param  defaultValue      The default value that will be used for this
150   *                           argument if no values are provided.  It may be
151   *                           {@code null} if there should not be a default
152   *                           value.
153   *
154   * @throws  ArgumentException  If there is a problem with the definition of
155   *                             this argument.
156   */
157  public BooleanValueArgument(final Character shortIdentifier,
158                              final String longIdentifier,
159                              final boolean isRequired,
160                              final String valuePlaceholder,
161                              final String description,
162                              final Boolean defaultValue)
163         throws ArgumentException
164  {
165    super(shortIdentifier, longIdentifier, isRequired, 1,
166         (valuePlaceholder == null)
167              ? INFO_PLACEHOLDER_TRUE_FALSE.get()
168              : valuePlaceholder,
169         description);
170
171    this.defaultValue = defaultValue;
172
173    value = null;
174  }
175
176
177
178  /**
179   * Creates a new Boolean value argument that is a "clean" copy of the provided
180   * source argument.
181   *
182   * @param  source  The source argument to use for this argument.
183   */
184  private BooleanValueArgument(final BooleanValueArgument source)
185  {
186    super(source);
187
188    defaultValue = source.defaultValue;
189    value        = null;
190  }
191
192
193
194  /**
195   * {@inheritDoc}
196   */
197  @Override()
198  public List<String> getValueStringRepresentations(final boolean useDefault)
199  {
200    if (value == null)
201    {
202      if (useDefault && (defaultValue != null))
203      {
204        return Collections.singletonList(defaultValue.toString());
205      }
206      else
207      {
208        return Collections.emptyList();
209      }
210    }
211    else
212    {
213      return Collections.singletonList(value.toString());
214    }
215  }
216
217
218
219  /**
220   * {@inheritDoc}
221   */
222  @Override()
223  protected boolean hasDefaultValue()
224  {
225    return (defaultValue != null);
226  }
227
228
229
230  /**
231   * Retrieves the default value for this argument, if defined.
232   *
233   * @return  The default value for this argument, or {@code null} if none is
234   *          defined.
235   */
236  public Boolean getDefaultValue()
237  {
238    return defaultValue;
239  }
240
241
242
243  /**
244   * Retrieves the value for this argument, if one was provided.
245   *
246   * @return  The value for this argument.  If no value was provided but a
247   *          default value was defined, then the default value will be
248   *          returned.  If no value was provided and no default value was
249   *          defined, then {@code null} will be returned.
250   */
251  public Boolean getValue()
252  {
253    if (value == null)
254    {
255      return defaultValue;
256    }
257    else
258    {
259      return value;
260    }
261  }
262
263
264
265  /**
266   * {@inheritDoc}
267   */
268  @Override()
269  protected void addValue(final String valueString)
270            throws ArgumentException
271  {
272    if (value != null)
273    {
274      throw new ArgumentException(
275           ERR_ARG_MAX_OCCURRENCES_EXCEEDED.get(getIdentifierString()));
276    }
277
278    final String lowerStr = StaticUtils.toLowerCase(valueString);
279    if (lowerStr.equals("true") || lowerStr.equals("t") ||
280        lowerStr.equals("yes") || lowerStr.equals("y") ||
281        lowerStr.equals("on") || lowerStr.equals("1"))
282    {
283      value = Boolean.TRUE;
284    }
285    else if (lowerStr.equals("false") || lowerStr.equals("f") ||
286             lowerStr.equals("no") || lowerStr.equals("n") ||
287             lowerStr.equals("off") || lowerStr.equals("0"))
288    {
289      value = Boolean.FALSE;
290    }
291    else
292    {
293      throw new ArgumentException(ERR_ARG_VALUE_NOT_ALLOWED.get(
294           valueString, getIdentifierString()));
295    }
296  }
297
298
299
300  /**
301   * {@inheritDoc}
302   */
303  @Override()
304  public String getDataTypeName()
305  {
306    return INFO_BOOLEAN_VALUE_TYPE_NAME.get();
307  }
308
309
310
311  /**
312   * {@inheritDoc}
313   */
314  @Override()
315  public String getValueConstraints()
316  {
317    return INFO_BOOLEAN_VALUE_CONSTRAINTS.get();
318  }
319
320
321
322  /**
323   * {@inheritDoc}
324   */
325  @Override()
326  protected void reset()
327  {
328    super.reset();
329    value = null;
330  }
331
332
333
334  /**
335   * {@inheritDoc}
336   */
337  @Override()
338  public BooleanValueArgument getCleanCopy()
339  {
340    return new BooleanValueArgument(this);
341  }
342
343
344
345  /**
346   * {@inheritDoc}
347   */
348  @Override()
349  protected void addToCommandLine(final List<String> argStrings)
350  {
351    if (value != null)
352    {
353      argStrings.add(getIdentifierString());
354      if (isSensitive())
355      {
356        argStrings.add("***REDACTED***");
357      }
358      else
359      {
360        argStrings.add(String.valueOf(value));
361      }
362    }
363  }
364
365
366
367  /**
368   * {@inheritDoc}
369   */
370  @Override()
371  public void toString(final StringBuilder buffer)
372  {
373    buffer.append("BooleanValueArgument(");
374    appendBasicToStringInfo(buffer);
375
376    if (defaultValue != null)
377    {
378      buffer.append(", defaultValue=");
379      buffer.append(defaultValue);
380    }
381
382    buffer.append(')');
383  }
384}