leif_good
leif_good

Reputation: 386

Apache Commons CLI 1.3.1: How to ignore unknown Arguments?

I used to work with Apache Commons Cli 1.2. I wanted the parser to ignore arguments if they are unknown (not added to an Options-Object).

Example (pseudocode):

Options specialOptions;
specialOptions.addOption(null, "help", false, "shows help");
specialOptions.addOption(null, "version", false, "show version");

CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args); //no third argument, since i dont want the program to stop parsing.
// run program with args: --help --unknown --version
// program shall parse --help AND --version, but ignore --unknown

I used this the solution by Pascal Schäfer: Can Apache Commons CLI options parser ignore unknown command-line options?

This worked fine for me on 1.2, and it works fine on 1.3.1 as well. But its deprecated. The parser I used got replaced by the DefaultParser. I looked up the functionalities, but there is no such method processOptions.

I really would like to use code that is not going to be deleted in later releases. Does anyone have an idea how to solve this problem?

Upvotes: 17

Views: 6828

Answers (4)

crmepham
crmepham

Reputation: 4760

Here is a solution that accounts for multiple option arguments.

@Override
public CommandLine parse(Options options, String... args) throws ParseException {
    final var knownArguments = new ArrayList<>();
    for (int i = 0, j = args.length; i < j; i++) {
        final var arg = args[i];
        if (options.hasOption(arg)) {
            final var option = options.getOption(arg);
            knownArguments.add(arg);

            if (option.hasArg()) {
                final var argsCount = option.getArgs();
                final var optionArgs = new ArrayList<>();

                for (int z = i + 1; z < args.length && optionArgs.size() < argsCount; z++) {
                    final var nextArg = args[z];
                    if (!options.hasOption(nextArg) && !nextArg.startsWith("-") && !nextArg.startsWith("--")) {
                        optionArgs.add(args[z]);
                    }
                }

                knownArguments.addAll(optionArgs);
            }
        }
    }

    return super.parse(options, knownArguments.toArray(String[]::new), false);
}

Upvotes: 0

aalosious
aalosious

Reputation: 598

Thanks, @kjp, for the suggestion; but the solutions doesn't work for arguments with values.

I've tried improving upon kjp's solution:

public class RelaxedParser extends DefaultParser {

@Override
public CommandLine parse(final Options options, final String[] arguments) throws ParseException {
    final List<String> knownArgs = new ArrayList<>();
    for (int i = 0; i < arguments.length; i++) {
        if (options.hasOption(arguments[i])) {
            knownArgs.add(arguments[i]);
            if (i + 1 < arguments.length && options.getOption(arguments[i]).hasArg()) {
                knownArgs.add(arguments[i + 1]);
            }
        }
    }
    return super.parse(options, knownArgs.toArray(new String[0]));
}

}

Upvotes: 7

Olivier Gr&#233;goire
Olivier Gr&#233;goire

Reputation: 35477

This should work for your use-case:

Options options = new Options();
CommandLine commandLine = new DefaultParser().parse(options, args, true);

The important part for you is the stopAtNonOption: true:

Flag indicating how unrecognized tokens are handled. true to stop the parsing and add the remaining tokens to the args list. false to throw an exception.

Docs at https://commons.apache.org/proper/commons-cli/javadocs/api-1.3.1/org/apache/commons/cli/DefaultParser.html#stopAtNonOption

Upvotes: 0

kjp
kjp

Reputation: 3116

The same approach as given in the solution by Pascal can be used here.

public class RelaxedParser extends DefaultParser {

    @Override
    public CommandLine parse(Options options, String[] arguments) throws ParseException {
        List<String> knownArguments = new ArrayList<>();
        for (String arg : arguments) {
            if (options.hasOption(arg)) {
                knownArguments.add(arg);
            }
        }
        return super.parse(options, knownArguments.toArray(new String[knownArguments.size()]));
    }
}

Or alternatively, remove unknown options from args as above and use the DefaultParser.

Upvotes: 3

Related Questions