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