Coverage Report - org.apache.commons.cli2.option.ArgumentImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ArgumentImpl
100%
111/111
97%
76/78
2.957
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.cli2.option;
 18  
 
 19  
 import java.util.Collections;
 20  
 import java.util.Comparator;
 21  
 import java.util.List;
 22  
 import java.util.ListIterator;
 23  
 import java.util.Set;
 24  
 import java.util.StringTokenizer;
 25  
 
 26  
 import org.apache.commons.cli2.Argument;
 27  
 import org.apache.commons.cli2.DisplaySetting;
 28  
 import org.apache.commons.cli2.HelpLine;
 29  
 import org.apache.commons.cli2.Option;
 30  
 import org.apache.commons.cli2.OptionException;
 31  
 import org.apache.commons.cli2.WriteableCommandLine;
 32  
 import org.apache.commons.cli2.resource.ResourceConstants;
 33  
 import org.apache.commons.cli2.resource.ResourceHelper;
 34  
 import org.apache.commons.cli2.validation.InvalidArgumentException;
 35  
 import org.apache.commons.cli2.validation.Validator;
 36  
 
 37  
 /**
 38  
  * An implementation of an Argument.
 39  
  */
 40  
 public class ArgumentImpl
 41  
     extends OptionImpl implements Argument {
 42  
     private static final char NUL = '\0';
 43  
 
 44  
     /**
 45  
      * The default value for the initial separator char.
 46  
      */
 47  
     public static final char DEFAULT_INITIAL_SEPARATOR = NUL;
 48  
 
 49  
     /**
 50  
      * The default value for the subsequent separator char.
 51  
      */
 52  
     public static final char DEFAULT_SUBSEQUENT_SEPARATOR = NUL;
 53  
 
 54  
     /**
 55  
      * The default token to indicate that remaining arguments should be consumed
 56  
      * as values.
 57  
      */
 58  
     public static final String DEFAULT_CONSUME_REMAINING = "--";
 59  
     private final String name;
 60  
     private final String description;
 61  
     private final int minimum;
 62  
     private final int maximum;
 63  
     private final char initialSeparator;
 64  
     private final char subsequentSeparator;
 65  
     private final boolean subsequentSplit;
 66  
     private final Validator validator;
 67  
     private final String consumeRemaining;
 68  
     private final List defaultValues;
 69  237
     private final ResourceHelper resources = ResourceHelper.getResourceHelper();
 70  
 
 71  
     /**
 72  
      * Creates a new Argument instance.
 73  
      *
 74  
      * @param name
 75  
      *            The name of the argument
 76  
      * @param description
 77  
      *            A description of the argument
 78  
      * @param minimum
 79  
      *            The minimum number of values needed to be valid
 80  
      * @param maximum
 81  
      *            The maximum number of values allowed to be valid
 82  
      * @param initialSeparator
 83  
      *            The char separating option from value
 84  
      * @param subsequentSeparator
 85  
      *            The char separating values from each other
 86  
      * @param validator
 87  
      *            The object responsible for validating the values
 88  
      * @param consumeRemaining
 89  
      *            The String used for the "consuming option" group
 90  
      * @param valueDefaults
 91  
      *            The values to be used if none are specified.
 92  
      * @param id
 93  
      *            The id of the option, 0 implies automatic assignment.
 94  
      *
 95  
      * @see OptionImpl#OptionImpl(int,boolean)
 96  
      */
 97  
     public ArgumentImpl(final String name,
 98  
                         final String description,
 99  
                         final int minimum,
 100  
                         final int maximum,
 101  
                         final char initialSeparator,
 102  
                         final char subsequentSeparator,
 103  
                         final Validator validator,
 104  
                         final String consumeRemaining,
 105  
                         final List valueDefaults,
 106  
                         final int id) {
 107  237
         super(id, false);
 108  
 
 109  237
         this.name = (name == null) ? "arg" : name;
 110  237
         this.description = description;
 111  237
         this.minimum = minimum;
 112  237
         this.maximum = maximum;
 113  237
         this.initialSeparator = initialSeparator;
 114  237
         this.subsequentSeparator = subsequentSeparator;
 115  237
         this.subsequentSplit = subsequentSeparator != NUL;
 116  237
         this.validator = validator;
 117  237
         this.consumeRemaining = consumeRemaining;
 118  237
         this.defaultValues = valueDefaults;
 119  
 
 120  237
         if (minimum > maximum) {
 121  1
             throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_MIN_EXCEEDS_MAX));
 122  
         }
 123  
 
 124  236
         if ((valueDefaults != null) && (valueDefaults.size() > 0)) {
 125  21
             if (valueDefaults.size() < minimum) {
 126  1
                 throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_TOO_FEW_DEFAULTS));
 127  
             }
 128  
 
 129  20
             if (valueDefaults.size() > maximum) {
 130  2
                 throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_TOO_MANY_DEFAULTS));
 131  
             }
 132  
         }
 133  233
     }
 134  
 
 135  
     public String getPreferredName() {
 136  950
         return name;
 137  
     }
 138  
 
 139  
     public void processValues(final WriteableCommandLine commandLine,
 140  
                               final ListIterator arguments,
 141  
                               final Option option)
 142  
         throws OptionException {
 143  
         // count of arguments processed for this option.
 144  87
         int argumentCount = commandLine.getUndefaultedValues(option).size();
 145  
 
 146  191
         while (arguments.hasNext() && (argumentCount < maximum)) {
 147  110
             final String allValuesQuoted = (String) arguments.next();
 148  110
             final String allValues = stripBoundaryQuotes(allValuesQuoted);
 149  
 
 150  
             // should we ignore things that look like options?
 151  110
             if (allValuesQuoted.equals(consumeRemaining)) {
 152  4
                 while (arguments.hasNext() && (argumentCount < maximum)) {
 153  2
                     ++argumentCount;
 154  2
                     commandLine.addValue(option, arguments.next());
 155  
                 }
 156  
             }
 157  
             // does it look like an option?
 158  108
             else if (commandLine.looksLikeOption(allValuesQuoted)) {
 159  5
                 arguments.previous();
 160  
 
 161  5
                 break;
 162  
             }
 163  
             // should we split the string up?
 164  103
             else if (subsequentSplit) {
 165  38
                 final StringTokenizer values =
 166  
                     new StringTokenizer(allValues, String.valueOf(subsequentSeparator));
 167  
 
 168  38
                 arguments.remove();
 169  
 
 170  87
                 while (values.hasMoreTokens() && (argumentCount < maximum)) {
 171  49
                     ++argumentCount;
 172  
 
 173  49
                     final String token = values.nextToken();
 174  49
                     commandLine.addValue(option, token);
 175  49
                     arguments.add(token);
 176  49
                 }
 177  
 
 178  38
                 if (values.hasMoreTokens()) {
 179  1
                     throw new OptionException(option, ResourceConstants.ARGUMENT_UNEXPECTED_VALUE,
 180  
                                               values.nextToken());
 181  
                 }
 182  37
             }
 183  
             // it must be a value as it is
 184  
             else {
 185  65
                 ++argumentCount;
 186  65
                 commandLine.addValue(option, allValues);
 187  
             }
 188  104
         }
 189  86
     }
 190  
 
 191  
     public boolean canProcess(final WriteableCommandLine commandLine,
 192  
                               final String arg) {
 193  23
         return true;
 194  
     }
 195  
 
 196  
     public Set getPrefixes() {
 197  405
         return Collections.EMPTY_SET;
 198  
     }
 199  
 
 200  
     public void process(WriteableCommandLine commandLine,
 201  
                         ListIterator args)
 202  
         throws OptionException {
 203  27
         processValues(commandLine, args, this);
 204  27
     }
 205  
 
 206  
     public char getInitialSeparator() {
 207  102
         return this.initialSeparator;
 208  
     }
 209  
 
 210  
     public char getSubsequentSeparator() {
 211  1
         return this.subsequentSeparator;
 212  
     }
 213  
 
 214  
     public Set getTriggers() {
 215  454
         return Collections.EMPTY_SET;
 216  
     }
 217  
 
 218  
     public String getConsumeRemaining() {
 219  1
         return this.consumeRemaining;
 220  
     }
 221  
 
 222  
     public List getDefaultValues() {
 223  9
         return this.defaultValues;
 224  
     }
 225  
 
 226  
     public Validator getValidator() {
 227  1
         return this.validator;
 228  
     }
 229  
 
 230  
     public void validate(final WriteableCommandLine commandLine)
 231  
         throws OptionException {
 232  23
         validate(commandLine, this);
 233  18
     }
 234  
 
 235  
     public void validate(final WriteableCommandLine commandLine,
 236  
                          final Option option)
 237  
         throws OptionException {
 238  74
         final List values = commandLine.getValues(option);
 239  
 
 240  74
         if (values.size() < minimum) {
 241  5
             throw new OptionException(option, ResourceConstants.ARGUMENT_MISSING_VALUES);
 242  
         }
 243  
 
 244  69
         if (values.size() > maximum) {
 245  1
             throw new OptionException(option, ResourceConstants.ARGUMENT_UNEXPECTED_VALUE,
 246  
                                       (String) values.get(maximum));
 247  
         }
 248  
 
 249  68
         if (validator != null) {
 250  
             try {
 251  5
                 validator.validate(values);
 252  1
             } catch (InvalidArgumentException ive) {
 253  1
                 throw new OptionException(option, ResourceConstants.ARGUMENT_UNEXPECTED_VALUE,
 254  
                                           ive.getMessage());
 255  4
             }
 256  
         }
 257  67
     }
 258  
 
 259  
     public void appendUsage(final StringBuffer buffer,
 260  
                             final Set helpSettings,
 261  
                             final Comparator comp) {
 262  
         // do we display the outer optionality
 263  57
         final boolean optional = helpSettings.contains(DisplaySetting.DISPLAY_OPTIONAL);
 264  
 
 265  
         // allow numbering if multiple args
 266  57
         final boolean numbered =
 267  
             (maximum > 1) && helpSettings.contains(DisplaySetting.DISPLAY_ARGUMENT_NUMBERED);
 268  
 
 269  57
         final boolean bracketed = helpSettings.contains(DisplaySetting.DISPLAY_ARGUMENT_BRACKETED);
 270  
 
 271  
         // if infinite args are allowed then crop the list
 272  57
         final int max = (maximum == Integer.MAX_VALUE) ? 2 : maximum;
 273  
 
 274  57
         int i = 0;
 275  
 
 276  
         // for each argument
 277  137
         while (i < max) {
 278  
             // if we're past the first add a space
 279  80
             if (i > 0) {
 280  24
                 buffer.append(' ');
 281  
             }
 282  
 
 283  
             // if the next arg is optional
 284  80
             if ((i >= minimum) && (optional || (i > 0))) {
 285  29
                 buffer.append('[');
 286  
             }
 287  
 
 288  80
             if (bracketed) {
 289  44
                 buffer.append('<');
 290  
             }
 291  
 
 292  
             // add name
 293  80
             buffer.append(name);
 294  80
             ++i;
 295  
 
 296  
             // if numbering
 297  80
             if (numbered) {
 298  21
                 buffer.append(i);
 299  
             }
 300  
 
 301  80
             if (bracketed) {
 302  44
                 buffer.append('>');
 303  
             }
 304  
         }
 305  
 
 306  
         // if infinite args are allowed
 307  57
         if (maximum == Integer.MAX_VALUE) {
 308  
             // append elipsis
 309  18
             buffer.append(" ...");
 310  
         }
 311  
 
 312  
         // for each argument
 313  137
         while (i > 0) {
 314  80
             --i;
 315  
 
 316  
             // if the next arg is optional
 317  80
             if ((i >= minimum) && (optional || (i > 0))) {
 318  29
                 buffer.append(']');
 319  
             }
 320  
         }
 321  57
     }
 322  
 
 323  
     public String getDescription() {
 324  581
         return description;
 325  
     }
 326  
 
 327  
     public List helpLines(final int depth,
 328  
                           final Set helpSettings,
 329  
                           final Comparator comp) {
 330  10
         final HelpLine helpLine = new HelpLineImpl(this, depth);
 331  
 
 332  10
         return Collections.singletonList(helpLine);
 333  
     }
 334  
 
 335  
     public int getMaximum() {
 336  22
         return maximum;
 337  
     }
 338  
 
 339  
     public int getMinimum() {
 340  27
         return minimum;
 341  
     }
 342  
 
 343  
     /**
 344  
      * If there are any leading or trailing quotes remove them from the
 345  
      * specified token.
 346  
      *
 347  
      * @param token
 348  
      *            the token to strip leading and trailing quotes
 349  
      *
 350  
      * @return String the possibly modified token
 351  
      */
 352  
     public String stripBoundaryQuotes(String token) {
 353  110
         if (!token.startsWith("\"") || !token.endsWith("\"")) {
 354  105
             return token;
 355  
         }
 356  
 
 357  5
         token = token.substring(1, token.length() - 1);
 358  
 
 359  5
         return token;
 360  
     }
 361  
 
 362  
     public boolean isRequired() {
 363  2
         return getMinimum() > 0;
 364  
     }
 365  
 
 366  
     public void defaults(final WriteableCommandLine commandLine) {
 367  28
         super.defaults(commandLine);
 368  28
         defaultValues(commandLine, this);
 369  28
     }
 370  
 
 371  
     public void defaultValues(final WriteableCommandLine commandLine,
 372  
                               final Option option) {
 373  110
         commandLine.setDefaultValues(option, defaultValues);
 374  110
     }
 375  
 }