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