Example #1
0
  /**
   * This is the overloaded {@link Object#toString()} method, and it is provided mainly for
   * debugging purposes.
   *
   * <p>
   *
   * @return A string representing the instance
   */
  public String toString() {

    StringBuffer sb = new StringBuffer();

    for (OptionSet set : optionSets.values()) {
      sb.append("Set: ");
      sb.append(set.getSetName());
      sb.append('\n');
      for (OptionData data : set.getOptionData()) {
        sb.append(data.toString());
        sb.append('\n');
      }
    }

    return sb.toString();
  }
Example #2
0
  /**
   * Run the checks for the given set.
   *
   * <p>
   *
   * @param setName The name for the set to check
   * @param ignoreUnmatched A boolean to select whether unmatched options can be ignored in the
   *     checks or not
   * @param requireDataLast A boolean to indicate whether the data items have to be the last ones on
   *     the command line or not
   *     <p>
   * @return A boolean indicating whether all checks were successful or not
   *     <p>
   * @throws IllegalArgumentException If either <code>setName</code> is <code>null</code>, or the
   *     set is unknown.
   */
  public boolean check(String setName, boolean ignoreUnmatched, boolean requireDataLast) {

    if (setName == null) throw new IllegalArgumentException(CLASS + ": setName may not be null");
    if (optionSets.get(setName) == null)
      throw new IllegalArgumentException(CLASS + ": Unknown OptionSet: " + setName);

    checkErrors = new StringBuffer();
    checkErrors.append("Checking set ");
    checkErrors.append(setName);
    checkErrors.append('\n');

    // .... Access the data for the set to use

    OptionSet set = optionSets.get(setName);
    java.util.ArrayList<OptionData> options = set.getOptionData();
    java.util.ArrayList<String> data = set.getData();
    java.util.ArrayList<String> unmatched = set.getUnmatched();

    // .... Catch some trivial cases

    if (options.size() == 0) { // No options have been defined at all
      if (arguments.length == 0) { // No arguments have been given: in this case, this is a success
        return true;
      } else {
        checkErrors.append("No options have been defined, nothing to check\n");
        return false;
      }
    } else if (arguments.length == 0
        && this.defaultMinData == 0) { // Options have been defined, but no arguments given
      return true;
    } else if (arguments.length == 0) { // Options have been defined, but no arguments given
      checkErrors.append(
          "Options have been defined, but no arguments have been given; nothing to check\n");
      return false;
    }

    // .... Parse all the arguments given

    int ipos = 0;
    int offset = 0;
    java.util.regex.Matcher m = null;
    String value = null;
    String detail = null;
    String next = null;
    String key = null;
    String pre = Character.toString(prefix.getName());
    boolean add = true;
    boolean[] matched = new boolean[arguments.length];

    for (int i = 0; i < matched.length; i++) // Initially, we assume there was no match at all
    matched[i] = false;

    while (true) {

      value = null;
      detail = null;
      offset = 0;
      add = true;
      key = arguments[ipos];

      for (OptionData optionData :
          options) { // For each argument, we may need to check all defined options
        m = optionData.getPattern().matcher(key);
        if (m.lookingAt()) {
          if (optionData.useValue()) { // The code section for value options
            if (optionData.useDetail()) {
              detail = m.group(1);
              offset = 2; // required for correct Matcher.group access below
            }
            if (optionData.getSeparator()
                == Separator.BLANK) { // In this case, the next argument must be the value
              if (ipos + 1
                  == arguments.length) { // The last argument, thus no value follows it: Error
                checkErrors.append("At end of arguments - no value found following argument ");
                checkErrors.append(key);
                checkErrors.append('\n');
                add = false;
              } else {
                next = arguments[ipos + 1];
                if (next.startsWith(pre)) { // The next one is an argument, not a value: Error
                  checkErrors.append("No value found following argument ");
                  checkErrors.append(key);
                  checkErrors.append('\n');
                  add = false;
                } else {
                  value = next;
                  matched[ipos++] = true; // Mark the key and the value
                  matched[ipos] = true;
                }
              }
            } else { // The value follows the separator in this case
              value = m.group(1 + offset);
              matched[ipos] = true;
            }
          } else { // Simple, non-value options
            matched[ipos] = true;
          }

          if (add) optionData.addResult(value, detail); // Store the result
          break; // No need to check more options, we have a match
        }
      }

      ipos++; // Advance to the next argument to check
      if (ipos >= arguments.length) break; // Terminating condition for the check loop
    }

    // .... Identify unmatched arguments and actual (non-option) data

    int first = -1; // Required later for requireDataLast
    for (int i = 0; i < matched.length; i++) { // Assemble the list of unmatched options
      if (!matched[i]) {
        if (arguments[i].startsWith(pre)) { // This is an unmatched option
          unmatched.add(arguments[i]);
          checkErrors.append("No matching option found for argument ");
          checkErrors.append(arguments[i]);
          checkErrors.append('\n');
        } else { // This is actual data
          if (first < 0) first = i;
          data.add(arguments[i]);
        }
      }
    }

    // .... Checks to determine overall success; start with multiplicity of options

    boolean err = true;

    for (OptionData optionData : options) {

      key = optionData.getKey();
      err = false; // Local check result for one option

      switch (optionData.getMultiplicity()) {
        case ONCE:
          if (optionData.getResultCount() != 1) err = true;
          break;
        case ONCE_OR_MORE:
          if (optionData.getResultCount() == 0) err = true;
          break;
        case ZERO_OR_ONE:
          if (optionData.getResultCount() > 1) err = true;
          break;
      }

      if (err) {
        checkErrors.append("Wrong number of occurences found for argument ");
        checkErrors.append(prefix.getName());
        checkErrors.append(key);
        checkErrors.append('\n');
        return false;
      }
    }

    // .... Check range for data

    if (data.size() < set.getMinData() || data.size() > set.getMaxData()) {
      checkErrors.append("Invalid number of data arguments: ");
      checkErrors.append(data.size());
      checkErrors.append(" (allowed range: ");
      checkErrors.append(set.getMinData());
      checkErrors.append(" ... ");
      checkErrors.append(set.getMaxData());
      checkErrors.append(")\n");
      return false;
    }

    // .... Check for location of the data in the list of command line arguments

    if (requireDataLast) {
      if (first + data.size() != arguments.length) {
        checkErrors.append(
            "Invalid data specification: data arguments are not the last ones on the command line\n");
        return false;
      }
    }

    // .... Check for unmatched arguments

    if (!ignoreUnmatched && unmatched.size() > 0) return false; // Don't accept unmatched arguments

    // .... If we made it to here, all checks were successful

    return true;
  }