001/* 002 * Copyright 2011-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2011-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2011-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.util.args; 037 038 039 040import java.text.ParseException; 041import java.util.ArrayList; 042import java.util.Collections; 043import java.util.List; 044 045import com.unboundid.util.Debug; 046import com.unboundid.util.Mutable; 047import com.unboundid.util.StaticUtils; 048import com.unboundid.util.ThreadSafety; 049import com.unboundid.util.ThreadSafetyLevel; 050 051import static com.unboundid.util.args.ArgsMessages.*; 052 053 054 055/** 056 * This class defines an argument whose values are intended to be argument 057 * strings as might be provided to a command-line application (e.g., 058 * "--arg1 arg1value --arg2 --arg3 arg3value"). Instances of this argument 059 * will have their own argument parser that may be used to process the argument 060 * strings. This type of argument may not be particularly useful for use in 061 * command-line applications, but may be used in other applications that may use 062 * arguments in other ways. 063 */ 064@Mutable() 065@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 066public final class ArgumentListArgument 067 extends Argument 068{ 069 /** 070 * The serial version UID for this serializable class. 071 */ 072 private static final long serialVersionUID = 1926330851837348378L; 073 074 075 076 // The argument parser that will be used to validate values given for this 077 // argument. 078 private final ArgumentParser parser; 079 080 // The list of argument parsers that correspond to values actually provided 081 // to this argument. 082 private final List<ArgumentParser> values; 083 084 // The string representations of the values provided for this argument. 085 private final List<String> valueStrings; 086 087 088 089 /** 090 * Creates a new argument list argument with the provided information. It 091 * will not be required, will permit at most one occurrence, and will use a 092 * default placeholder. 093 * 094 * @param shortIdentifier The short identifier for this argument. It may 095 * not be {@code null} if the long identifier is 096 * {@code null}. 097 * @param longIdentifier The long identifier for this argument. It may 098 * not be {@code null} if the short identifier is 099 * {@code null}. 100 * @param description A human-readable description for this argument. 101 * It must not be {@code null}. 102 * @param parser The argument parser that will be used to 103 * process values provided for this argument. 104 * 105 * @throws ArgumentException If there is a problem with the definition of 106 * this argument. 107 */ 108 public ArgumentListArgument(final Character shortIdentifier, 109 final String longIdentifier, 110 final String description, 111 final ArgumentParser parser) 112 throws ArgumentException 113 { 114 this(shortIdentifier, longIdentifier, false, 1, null, description, parser); 115 } 116 117 118 119 /** 120 * Creates a new argument list argument with the provided information. 121 * 122 * @param shortIdentifier The short identifier for this argument. It may 123 * not be {@code null} if the long identifier is 124 * {@code null}. 125 * @param longIdentifier The long identifier for this argument. It may 126 * not be {@code null} if the short identifier is 127 * {@code null}. 128 * @param isRequired Indicates whether this argument is required to 129 * be provided. 130 * @param maxOccurrences The maximum number of times this argument may be 131 * provided on the command line. A value less than 132 * or equal to zero indicates that it may be present 133 * any number of times. 134 * @param valuePlaceholder A placeholder to display in usage information to 135 * indicate that a value must be provided. It may 136 * be {@code null} if a default placeholder should 137 * be used. 138 * @param description A human-readable description for this argument. 139 * It must not be {@code null}. 140 * @param parser The argument parser that will be used to 141 * process values provided for this argument. 142 * 143 * @throws ArgumentException If there is a problem with the definition of 144 * this argument. 145 */ 146 public ArgumentListArgument(final Character shortIdentifier, 147 final String longIdentifier, 148 final boolean isRequired, 149 final int maxOccurrences, 150 final String valuePlaceholder, 151 final String description, 152 final ArgumentParser parser) 153 throws ArgumentException 154 { 155 super(shortIdentifier, longIdentifier, isRequired, maxOccurrences, 156 (valuePlaceholder == null) 157 ? INFO_PLACEHOLDER_ARGS.get() 158 : valuePlaceholder, 159 description); 160 161 this.parser = parser.getCleanCopy(); 162 163 values = new ArrayList<>(10); 164 valueStrings = new ArrayList<>(10); 165 } 166 167 168 169 /** 170 * Creates a new argument list argument that is a "clean" copy of the provided 171 * source argument. 172 * 173 * @param source The source argument to use for this argument. 174 */ 175 private ArgumentListArgument(final ArgumentListArgument source) 176 { 177 super(source); 178 179 parser = source.parser; 180 values = new ArrayList<>(10); 181 valueStrings = new ArrayList<>(10); 182 } 183 184 185 186 /** 187 * Retrieves a "clean" copy of the argument parser that will be used to 188 * process values provided for this argument. 189 * 190 * @return A "clean" copy of the argument parser that will be used to process 191 * values provided for this argument. 192 */ 193 public ArgumentParser getCleanParser() 194 { 195 return parser.getCleanCopy(); 196 } 197 198 199 200 /** 201 * {@inheritDoc} 202 */ 203 @Override() 204 protected void addValue(final String valueString) 205 throws ArgumentException 206 { 207 final List<String> argList; 208 try 209 { 210 argList = StaticUtils.toArgumentList(valueString); 211 } 212 catch (final ParseException pe) 213 { 214 Debug.debugException(pe); 215 throw new ArgumentException(ERR_ARG_LIST_MALFORMED_VALUE.get(valueString, 216 getIdentifierString(), pe.getMessage()), pe); 217 } 218 219 final String[] args = new String[argList.size()]; 220 argList.toArray(args); 221 222 final ArgumentParser p = parser.getCleanCopy(); 223 try 224 { 225 p.parse(args); 226 } 227 catch (final ArgumentException ae) 228 { 229 Debug.debugException(ae); 230 throw new ArgumentException(ERR_ARG_LIST_INVALID_VALUE.get(valueString, 231 getIdentifierString(), ae.getMessage()), ae); 232 } 233 234 values.add(p); 235 valueStrings.add(valueString); 236 } 237 238 239 240 /** 241 * Retrieves the list of argument parsers that have been used to process 242 * values provided to this argument. 243 * 244 * @return The list of argument parsers that have been used to process values 245 * provided to this argument. 246 */ 247 public List<ArgumentParser> getValueParsers() 248 { 249 return Collections.unmodifiableList(values); 250 } 251 252 253 254 /** 255 * Retrieves the list of the string representations of the values provided to 256 * this argument. 257 * 258 * @return The list of the string representations of the values provided to 259 * this argument. 260 */ 261 public List<String> getValueStrings() 262 { 263 return Collections.unmodifiableList(valueStrings); 264 } 265 266 267 268 /** 269 * {@inheritDoc} 270 */ 271 @Override() 272 public List<String> getValueStringRepresentations(final boolean useDefault) 273 { 274 return Collections.unmodifiableList(valueStrings); 275 } 276 277 278 279 /** 280 * {@inheritDoc} 281 */ 282 @Override() 283 protected boolean hasDefaultValue() 284 { 285 return false; 286 } 287 288 289 290 /** 291 * {@inheritDoc} 292 */ 293 @Override() 294 public String getDataTypeName() 295 { 296 return INFO_ARG_LIST_TYPE_NAME.get(); 297 } 298 299 300 301 /** 302 * {@inheritDoc} 303 */ 304 @Override() 305 public String getValueConstraints() 306 { 307 return INFO_ARG_LIST_CONSTRAINTS.get(); 308 } 309 310 311 312 /** 313 * {@inheritDoc} 314 */ 315 @Override() 316 protected void reset() 317 { 318 super.reset(); 319 values.clear(); 320 } 321 322 323 324 /** 325 * {@inheritDoc} 326 */ 327 @Override() 328 public ArgumentListArgument getCleanCopy() 329 { 330 return new ArgumentListArgument(this); 331 } 332 333 334 335 /** 336 * {@inheritDoc} 337 */ 338 @Override() 339 protected void addToCommandLine(final List<String> argStrings) 340 { 341 if (valueStrings != null) 342 { 343 for (final String s : valueStrings) 344 { 345 argStrings.add(getIdentifierString()); 346 if (isSensitive()) 347 { 348 argStrings.add("***REDACTED***"); 349 } 350 else 351 { 352 argStrings.add(s); 353 } 354 } 355 } 356 } 357 358 359 360 /** 361 * {@inheritDoc} 362 */ 363 @Override() 364 public void toString(final StringBuilder buffer) 365 { 366 buffer.append("ArgumentListArgument("); 367 appendBasicToStringInfo(buffer); 368 buffer.append(", parser="); 369 parser.toString(buffer); 370 buffer.append(')'); 371 } 372}