001    /*
002     * Copyright 2011-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2011-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     */
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.
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    }