001/*
002 * Copyright 2008-2015 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2008-2015 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 */
021package com.unboundid.util.args;
022
023
024
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.Collections;
028import java.util.Iterator;
029import java.util.List;
030
031import com.unboundid.ldap.sdk.DN;
032import com.unboundid.ldap.sdk.LDAPException;
033import com.unboundid.util.Mutable;
034import com.unboundid.util.ThreadSafety;
035import com.unboundid.util.ThreadSafetyLevel;
036
037import static com.unboundid.util.Debug.*;
038import static com.unboundid.util.args.ArgsMessages.*;
039
040
041
042/**
043 * This class defines an argument that is intended to hold one or more
044 * distinguished name values.  DN arguments must take values, and those values
045 * must be able to be parsed as distinguished names.
046 */
047@Mutable()
048@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
049public final class DNArgument
050       extends Argument
051{
052  /**
053   * The serial version UID for this serializable class.
054   */
055  private static final long serialVersionUID = 7956577383262400167L;
056
057
058
059  // The set of values assigned to this argument.
060  private final ArrayList<DN> values;
061
062  // The argument value validators that have been registered for this argument.
063  private final List<ArgumentValueValidator> validators;
064
065  // The list of default values for this argument.
066  private final List<DN> defaultValues;
067
068
069
070  /**
071   * Creates a new DN argument with the provided information.  It will not have
072   * a default value.
073   *
074   * @param  shortIdentifier   The short identifier for this argument.  It may
075   *                           not be {@code null} if the long identifier is
076   *                           {@code null}.
077   * @param  longIdentifier    The long identifier for this argument.  It may
078   *                           not be {@code null} if the short identifier is
079   *                           {@code null}.
080   * @param  isRequired        Indicates whether this argument is required to
081   *                           be provided.
082   * @param  maxOccurrences    The maximum number of times this argument may be
083   *                           provided on the command line.  A value less than
084   *                           or equal to zero indicates that it may be present
085   *                           any number of times.
086   * @param  valuePlaceholder  A placeholder to display in usage information to
087   *                           indicate that a value must be provided.  It must
088   *                           not be {@code null}.
089   * @param  description       A human-readable description for this argument.
090   *                           It must not be {@code null}.
091   *
092   * @throws  ArgumentException  If there is a problem with the definition of
093   *                             this argument.
094   */
095  public DNArgument(final Character shortIdentifier,
096                    final String longIdentifier, final boolean isRequired,
097                    final int maxOccurrences, final String valuePlaceholder,
098                    final String description)
099         throws ArgumentException
100  {
101    this(shortIdentifier, longIdentifier, isRequired,  maxOccurrences,
102         valuePlaceholder, description, (List<DN>) null);
103  }
104
105
106
107  /**
108   * Creates a new DN argument with the provided information.
109   *
110   * @param  shortIdentifier   The short identifier for this argument.  It may
111   *                           not be {@code null} if the long identifier is
112   *                           {@code null}.
113   * @param  longIdentifier    The long identifier for this argument.  It may
114   *                           not be {@code null} if the short identifier is
115   *                           {@code null}.
116   * @param  isRequired        Indicates whether this argument is required to
117   *                           be provided.
118   * @param  maxOccurrences    The maximum number of times this argument may be
119   *                           provided on the command line.  A value less than
120   *                           or equal to zero indicates that it may be present
121   *                           any number of times.
122   * @param  valuePlaceholder  A placeholder to display in usage information to
123   *                           indicate that a value must be provided.  It must
124   *                           not be {@code null}.
125   * @param  description       A human-readable description for this argument.
126   *                           It must not be {@code null}.
127   * @param  defaultValue      The default value to use for this argument if no
128   *                           values were provided.
129   *
130   * @throws  ArgumentException  If there is a problem with the definition of
131   *                             this argument.
132   */
133  public DNArgument(final Character shortIdentifier,
134                    final String longIdentifier, final boolean isRequired,
135                    final int maxOccurrences, final String valuePlaceholder,
136                    final String description, final DN defaultValue)
137         throws ArgumentException
138  {
139    this(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
140         valuePlaceholder, description,
141         ((defaultValue == null) ? null : Arrays.asList(defaultValue)));
142  }
143
144
145
146  /**
147   * Creates a new DN argument with the provided information.
148   *
149   * @param  shortIdentifier   The short identifier for this argument.  It may
150   *                           not be {@code null} if the long identifier is
151   *                           {@code null}.
152   * @param  longIdentifier    The long identifier for this argument.  It may
153   *                           not be {@code null} if the short identifier is
154   *                           {@code null}.
155   * @param  isRequired        Indicates whether this argument is required to
156   *                           be provided.
157   * @param  maxOccurrences    The maximum number of times this argument may be
158   *                           provided on the command line.  A value less than
159   *                           or equal to zero indicates that it may be present
160   *                           any number of times.
161   * @param  valuePlaceholder  A placeholder to display in usage information to
162   *                           indicate that a value must be provided.  It must
163   *                           not be {@code null}.
164   * @param  description       A human-readable description for this argument.
165   *                           It must not be {@code null}.
166   * @param  defaultValues     The set of default values to use for this
167   *                           argument if no values were provided.
168   *
169   * @throws  ArgumentException  If there is a problem with the definition of
170   *                             this argument.
171   */
172  public DNArgument(final Character shortIdentifier,
173                    final String longIdentifier, final boolean isRequired,
174                    final int maxOccurrences, final String valuePlaceholder,
175                    final String description, final List<DN> defaultValues)
176         throws ArgumentException
177  {
178    super(shortIdentifier, longIdentifier, isRequired,  maxOccurrences,
179          valuePlaceholder, description);
180
181    if (valuePlaceholder == null)
182    {
183      throw new ArgumentException(ERR_ARG_MUST_TAKE_VALUE.get(
184                                       getIdentifierString()));
185    }
186
187    if ((defaultValues == null) || defaultValues.isEmpty())
188    {
189      this.defaultValues = null;
190    }
191    else
192    {
193      this.defaultValues = Collections.unmodifiableList(defaultValues);
194    }
195
196    values = new ArrayList<DN>(5);
197    validators = new ArrayList<ArgumentValueValidator>(5);
198  }
199
200
201
202  /**
203   * Creates a new DN argument that is a "clean" copy of the provided source
204   * argument.
205   *
206   * @param  source  The source argument to use for this argument.
207   */
208  private DNArgument(final DNArgument source)
209  {
210    super(source);
211
212    defaultValues = source.defaultValues;
213    values        = new ArrayList<DN>(5);
214    validators    = new ArrayList<ArgumentValueValidator>(source.validators);
215  }
216
217
218
219  /**
220   * Retrieves the list of default values for this argument, which will be used
221   * if no values were provided.
222   *
223   * @return   The list of default values for this argument, or {@code null} if
224   *           there are no default values.
225   */
226  public List<DN> getDefaultValues()
227  {
228    return defaultValues;
229  }
230
231
232
233  /**
234   * Updates this argument to ensure that the provided validator will be invoked
235   * for any values provided to this argument.  This validator will be invoked
236   * after all other validation has been performed for this argument.
237   *
238   * @param  validator  The argument value validator to be invoked.  It must not
239   *                    be {@code null}.
240   */
241  public void addValueValidator(final ArgumentValueValidator validator)
242  {
243    validators.add(validator);
244  }
245
246
247
248  /**
249   * {@inheritDoc}
250   */
251  @Override()
252  protected void addValue(final String valueString)
253            throws ArgumentException
254  {
255    final DN parsedDN;
256    try
257    {
258      parsedDN = new DN(valueString);
259    }
260    catch (LDAPException le)
261    {
262      debugException(le);
263      throw new ArgumentException(ERR_DN_VALUE_NOT_DN.get(valueString,
264                                       getIdentifierString(), le.getMessage()),
265                                  le);
266    }
267
268    if (values.size() >= getMaxOccurrences())
269    {
270      throw new ArgumentException(ERR_ARG_MAX_OCCURRENCES_EXCEEDED.get(
271                                       getIdentifierString()));
272    }
273
274    for (final ArgumentValueValidator v : validators)
275    {
276      v.validateArgumentValue(this, valueString);
277    }
278
279    values.add(parsedDN);
280  }
281
282
283
284  /**
285   * Retrieves the value for this argument, or the default value if none was
286   * provided.  If there are multiple values, then the first will be returned.
287   *
288   * @return  The value for this argument, or the default value if none was
289   *          provided, or {@code null} if there is no value and no default
290   *          value.
291   */
292  public DN getValue()
293  {
294    if (values.isEmpty())
295    {
296      if ((defaultValues == null) || defaultValues.isEmpty())
297      {
298        return null;
299      }
300      else
301      {
302        return defaultValues.get(0);
303      }
304    }
305    else
306    {
307      return values.get(0);
308    }
309  }
310
311
312
313  /**
314   * Retrieves the set of values for this argument.
315   *
316   * @return  The set of values for this argument.
317   */
318  public List<DN> getValues()
319  {
320    if (values.isEmpty() && (defaultValues != null))
321    {
322      return defaultValues;
323    }
324
325    return Collections.unmodifiableList(values);
326  }
327
328
329
330  /**
331   * Retrieves a string representation of the value for this argument, or a
332   * string representation of the default value if none was provided.  If there
333   * are multiple values, then the first will be returned.
334   *
335   * @return  The string representation of the value for this argument, or the
336   *          string representation of the default value if none was provided,
337   *          or {@code null} if there is no value and no default value.
338   */
339  public String getStringValue()
340  {
341    final DN valueDN = getValue();
342    if (valueDN == null)
343    {
344      return null;
345    }
346
347    return valueDN.toString();
348  }
349
350
351
352  /**
353   * {@inheritDoc}
354   */
355  @Override()
356  protected boolean hasDefaultValue()
357  {
358    return ((defaultValues != null) && (! defaultValues.isEmpty()));
359  }
360
361
362
363  /**
364   * {@inheritDoc}
365   */
366  @Override()
367  public String getDataTypeName()
368  {
369    return INFO_DN_TYPE_NAME.get();
370  }
371
372
373
374  /**
375   * {@inheritDoc}
376   */
377  @Override()
378  public String getValueConstraints()
379  {
380    return INFO_DN_CONSTRAINTS.get();
381  }
382
383
384
385  /**
386   * {@inheritDoc}
387   */
388  @Override()
389  public DNArgument getCleanCopy()
390  {
391    return new DNArgument(this);
392  }
393
394
395
396  /**
397   * {@inheritDoc}
398   */
399  @Override()
400  public void toString(final StringBuilder buffer)
401  {
402    buffer.append("DNArgument(");
403    appendBasicToStringInfo(buffer);
404
405    if ((defaultValues != null) && (! defaultValues.isEmpty()))
406    {
407      if (defaultValues.size() == 1)
408      {
409        buffer.append(", defaultValue='");
410        buffer.append(defaultValues.get(0).toString());
411      }
412      else
413      {
414        buffer.append(", defaultValues={");
415
416        final Iterator<DN> iterator = defaultValues.iterator();
417        while (iterator.hasNext())
418        {
419          buffer.append('\'');
420          buffer.append(iterator.next().toString());
421          buffer.append('\'');
422
423          if (iterator.hasNext())
424          {
425            buffer.append(", ");
426          }
427        }
428
429        buffer.append('}');
430      }
431    }
432
433    buffer.append(')');
434  }
435}