001 /*
002 * Copyright 2011-2016 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2011-2016 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.text.ParseException;
026 import java.util.ArrayList;
027 import java.util.Collections;
028 import java.util.List;
029
030 import com.unboundid.util.Debug;
031 import com.unboundid.util.Mutable;
032 import com.unboundid.util.StaticUtils;
033 import com.unboundid.util.ThreadSafety;
034 import com.unboundid.util.ThreadSafetyLevel;
035
036 import 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)
051 public 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. It
076 * will not be required, will permit at most one occurrence, and will use a
077 * default placeholder.
078 *
079 * @param shortIdentifier The short identifier for this argument. It may
080 * not be {@code null} if the long identifier is
081 * {@code null}.
082 * @param longIdentifier The long identifier for this argument. It may
083 * not be {@code null} if the short identifier is
084 * {@code null}.
085 * @param description A human-readable description for this argument.
086 * It must not be {@code null}.
087 * @param parser The argument parser that will be used to
088 * process values provided for this argument.
089 *
090 * @throws ArgumentException If there is a problem with the definition of
091 * this argument.
092 */
093 public ArgumentListArgument(final Character shortIdentifier,
094 final String longIdentifier,
095 final String description,
096 final ArgumentParser parser)
097 throws ArgumentException
098 {
099 this(shortIdentifier, longIdentifier, false, 1, null, description, parser);
100 }
101
102
103
104 /**
105 * Creates a new argument list 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 may
121 * be {@code null} if a default placeholder should
122 * be used.
123 * @param description A human-readable description for this argument.
124 * It must not be {@code null}.
125 * @param parser The argument parser that will be used to
126 * process values provided for this argument.
127 *
128 * @throws ArgumentException If there is a problem with the definition of
129 * this argument.
130 */
131 public ArgumentListArgument(final Character shortIdentifier,
132 final String longIdentifier,
133 final boolean isRequired,
134 final int maxOccurrences,
135 final String valuePlaceholder,
136 final String description,
137 final ArgumentParser parser)
138 throws ArgumentException
139 {
140 super(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
141 (valuePlaceholder == null)
142 ? INFO_PLACEHOLDER_ARGS.get()
143 : valuePlaceholder,
144 description);
145
146 this.parser = parser.getCleanCopy();
147
148 values = new ArrayList<ArgumentParser>();
149 valueStrings = new ArrayList<String>();
150 }
151
152
153
154 /**
155 * Creates a new argument list argument that is a "clean" copy of the provided
156 * source argument.
157 *
158 * @param source The source argument to use for this argument.
159 */
160 private ArgumentListArgument(final ArgumentListArgument source)
161 {
162 super(source);
163
164 parser = source.parser;
165 values = new ArrayList<ArgumentParser>();
166 valueStrings = new ArrayList<String>();
167 }
168
169
170
171 /**
172 * Retrieves a "clean" copy of the argument parser that will be used to
173 * process values provided for this argument.
174 *
175 * @return A "clean" copy of the argument parser that will be used to process
176 * values provided for this argument.
177 */
178 public ArgumentParser getCleanParser()
179 {
180 return parser.getCleanCopy();
181 }
182
183
184
185 /**
186 * {@inheritDoc}
187 */
188 @Override()
189 protected void addValue(final String valueString)
190 throws ArgumentException
191 {
192 final List<String> argList;
193 try
194 {
195 argList = StaticUtils.toArgumentList(valueString);
196 }
197 catch (final ParseException pe)
198 {
199 Debug.debugException(pe);
200 throw new ArgumentException(ERR_ARG_LIST_MALFORMED_VALUE.get(valueString,
201 getIdentifierString(), pe.getMessage()), pe);
202 }
203
204 final String[] args = new String[argList.size()];
205 argList.toArray(args);
206
207 final ArgumentParser p = parser.getCleanCopy();
208 try
209 {
210 p.parse(args);
211 }
212 catch (final ArgumentException ae)
213 {
214 Debug.debugException(ae);
215 throw new ArgumentException(ERR_ARG_LIST_INVALID_VALUE.get(valueString,
216 getIdentifierString(), ae.getMessage()), ae);
217 }
218
219 values.add(p);
220 valueStrings.add(valueString);
221 }
222
223
224
225 /**
226 * Retrieves the list of argument parsers that have been used to process
227 * values provided to this argument.
228 *
229 * @return The list of argument parsers that have been used to process values
230 * provided to this argument.
231 */
232 public List<ArgumentParser> getValueParsers()
233 {
234 return Collections.unmodifiableList(values);
235 }
236
237
238
239 /**
240 * Retrieves the list of the string representations of the values provided to
241 * this argument.
242 *
243 * @return The list of the string representations of the values provided to
244 * this argument.
245 */
246 public List<String> getValueStrings()
247 {
248 return Collections.unmodifiableList(valueStrings);
249 }
250
251
252
253 /**
254 * {@inheritDoc}
255 */
256 @Override()
257 public List<String> getValueStringRepresentations(final boolean useDefault)
258 {
259 return Collections.unmodifiableList(valueStrings);
260 }
261
262
263
264 /**
265 * {@inheritDoc}
266 */
267 @Override()
268 protected boolean hasDefaultValue()
269 {
270 return false;
271 }
272
273
274
275 /**
276 * {@inheritDoc}
277 */
278 @Override()
279 public String getDataTypeName()
280 {
281 return INFO_ARG_LIST_TYPE_NAME.get();
282 }
283
284
285
286 /**
287 * {@inheritDoc}
288 */
289 @Override()
290 public String getValueConstraints()
291 {
292 return INFO_ARG_LIST_CONSTRAINTS.get();
293 }
294
295
296
297 /**
298 * {@inheritDoc}
299 */
300 @Override()
301 protected void reset()
302 {
303 super.reset();
304 values.clear();
305 }
306
307
308
309 /**
310 * {@inheritDoc}
311 */
312 @Override()
313 public ArgumentListArgument getCleanCopy()
314 {
315 return new ArgumentListArgument(this);
316 }
317
318
319
320 /**
321 * {@inheritDoc}
322 */
323 @Override()
324 protected void addToCommandLine(final List<String> argStrings)
325 {
326 if (valueStrings != null)
327 {
328 for (final String s : valueStrings)
329 {
330 argStrings.add(getIdentifierString());
331 if (isSensitive())
332 {
333 argStrings.add("***REDACTED***");
334 }
335 else
336 {
337 argStrings.add(s);
338 }
339 }
340 }
341 }
342
343
344
345 /**
346 * {@inheritDoc}
347 */
348 @Override()
349 public void toString(final StringBuilder buffer)
350 {
351 buffer.append("ArgumentListArgument(");
352 appendBasicToStringInfo(buffer);
353 buffer.append(", parser=");
354 parser.toString(buffer);
355 buffer.append(')');
356 }
357 }