001/*
002 * Copyright 2011-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2011-2014 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.text.ParseException;
026import java.util.ArrayList;
027import java.util.Collections;
028import java.util.List;
029
030import com.unboundid.util.Debug;
031import com.unboundid.util.Mutable;
032import com.unboundid.util.StaticUtils;
033import com.unboundid.util.ThreadSafety;
034import com.unboundid.util.ThreadSafetyLevel;
035
036import static com.unboundid.util.args.ArgsMessages.*;
037
038
039
040/**
041 * This class defines an argument whose values are intended to be argument
042 * strings as might be provided to a command-line application (e.g.,
043 * "--arg1 arg1value --arg2 --arg3 arg3value").  Instances of this argument
044 * will have their own argument parser that may be used to process the argument
045 * strings.  This type of argument may not be particularly useful for use in
046 * command-line applications, but may be used in other applications that may use
047 * arguments in other ways.
048 */
049@Mutable()
050@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
051public final class ArgumentListArgument
052       extends Argument
053{
054  /**
055   * The serial version UID for this serializable class.
056   */
057  private static final long serialVersionUID = 1926330851837348378L;
058
059
060
061  // The argument parser that will be used to validate values given for this
062  // argument.
063  private final ArgumentParser parser;
064
065  // The list of argument parsers that correspond to values actually provided
066  // to this argument.
067  private final List<ArgumentParser> values;
068
069  // The string representations of the values provided for this argument.
070  private final List<String> valueStrings;
071
072
073
074  /**
075   * Creates a new argument list argument with the provided information.
076   *
077   * @param  shortIdentifier   The short identifier for this argument.  It may
078   *                           not be {@code null} if the long identifier is
079   *                           {@code null}.
080   * @param  longIdentifier    The long identifier for this argument.  It may
081   *                           not be {@code null} if the short identifier is
082   *                           {@code null}.
083   * @param  isRequired        Indicates whether this argument is required to
084   *                           be provided.
085   * @param  maxOccurrences    The maximum number of times this argument may be
086   *                           provided on the command line.  A value less than
087   *                           or equal to zero indicates that it may be present
088   *                           any number of times.
089   * @param  valuePlaceholder  A placeholder to display in usage information to
090   *                           indicate that a value must be provided.  It must
091   *                           not be {@code null}.
092   * @param  description       A human-readable description for this argument.
093   *                           It must not be {@code null}.
094   * @param  parser            The argument parser that will be used to
095   *                           process values provided for this argument.
096   *
097   * @throws  ArgumentException  If there is a problem with the definition of
098   *                             this argument.
099   */
100  public ArgumentListArgument(final Character shortIdentifier,
101                              final String longIdentifier,
102                              final boolean isRequired,
103                              final int maxOccurrences,
104                              final String valuePlaceholder,
105                              final String description,
106                              final ArgumentParser parser)
107         throws ArgumentException
108  {
109    super(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
110         valuePlaceholder, description);
111
112    this.parser = parser.getCleanCopy();
113
114    values = new ArrayList<ArgumentParser>();
115    valueStrings = new ArrayList<String>();
116  }
117
118
119
120  /**
121   * Creates a new argument list argument that is a "clean" copy of the provided
122   * source argument.
123   *
124   * @param  source  The source argument to use for this argument.
125   */
126  private ArgumentListArgument(final ArgumentListArgument source)
127  {
128    super(source);
129
130    parser = source.parser;
131    values = new ArrayList<ArgumentParser>();
132    valueStrings = new ArrayList<String>();
133  }
134
135
136
137  /**
138   * Retrieves a "clean" copy of the argument parser that will be used to
139   * process values provided for this argument.
140   *
141   * @return  A "clean" copy of the argument parser that will be used to process
142   *          values provided for this argument.
143   */
144  public ArgumentParser getCleanParser()
145  {
146    return parser.getCleanCopy();
147  }
148
149
150
151  /**
152   * {@inheritDoc}
153   */
154  @Override()
155  protected void addValue(final String valueString)
156            throws ArgumentException
157  {
158    final List<String> argList;
159    try
160    {
161      argList = StaticUtils.toArgumentList(valueString);
162    }
163    catch (final ParseException pe)
164    {
165      Debug.debugException(pe);
166      throw new ArgumentException(ERR_ARG_LIST_MALFORMED_VALUE.get(valueString,
167           getIdentifierString(), pe.getMessage()), pe);
168    }
169
170    final String[] args = new String[argList.size()];
171    argList.toArray(args);
172
173    final ArgumentParser p = parser.getCleanCopy();
174    try
175    {
176      p.parse(args);
177    }
178    catch (final ArgumentException ae)
179    {
180      Debug.debugException(ae);
181      throw new ArgumentException(ERR_ARG_LIST_INVALID_VALUE.get(valueString,
182      getIdentifierString(), ae.getMessage()), ae);
183    }
184
185    values.add(p);
186    valueStrings.add(valueString);
187  }
188
189
190
191  /**
192   * Retrieves the list of argument parsers that have been used to process
193   * values provided to this argument.
194   *
195   * @return  The list of argument parsers that have been used to process values
196   *          provided to this argument.
197   */
198  public List<ArgumentParser> getValueParsers()
199  {
200    return Collections.unmodifiableList(values);
201  }
202
203
204
205  /**
206   * Retrieves the list of the string representations of the values provided to
207   * this argument.
208   *
209   * @return  The list of the string representations of the values provided to
210   *          this argument.
211   */
212  public List<String> getValueStrings()
213  {
214    return Collections.unmodifiableList(valueStrings);
215  }
216
217
218
219  /**
220   * {@inheritDoc}
221   */
222  @Override()
223  protected boolean hasDefaultValue()
224  {
225    return false;
226  }
227
228
229
230  /**
231   * {@inheritDoc}
232   */
233  @Override()
234  public String getDataTypeName()
235  {
236    return INFO_ARG_LIST_TYPE_NAME.get();
237  }
238
239
240
241  /**
242   * {@inheritDoc}
243   */
244  @Override()
245  public String getValueConstraints()
246  {
247    return INFO_ARG_LIST_CONSTRAINTS.get();
248  }
249
250
251
252  /**
253   * {@inheritDoc}
254   */
255  @Override()
256  public ArgumentListArgument getCleanCopy()
257  {
258    return new ArgumentListArgument(this);
259  }
260
261
262
263  /**
264   * {@inheritDoc}
265   */
266  @Override()
267  public void toString(final StringBuilder buffer)
268  {
269    buffer.append("ArgumentListArgument(");
270    appendBasicToStringInfo(buffer);
271    buffer.append(", parser=");
272    parser.toString(buffer);
273    buffer.append(')');
274  }
275}