/** * 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(); }
/** * 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; }