4
@Options(name="--in-file")
String fileName;

@Option(name="--table")
String table;

I would like to make the --table option be required if and only if no value is given for --in-file. How might I go about doing this? I know that there are some solutions (I think at least) where I can do this with multiple classes, but that seems like overkill for only two arguments in a simple program.

I know I can also manually check the values after the parsing is completed, but that seems to defeat the purpose of using args4j.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128

2 Answers2

4

I realized I can use the forbids annotation option to most of accomplish this. You only need the tag on one or the other, but I put it on both for completeness.

Using forbids

@Options(name="--in-file", forbids{"--table"})
String fileName;

@Option(name="--table", forbids={"--in-file"})
String table;

One could use the depends annotation for reverse logic.


Why the above is not complete:

The above is only partially correct: the solution still fails if you want one of the options to be required if another isn't given. The required part overrules the forbids, so doing

@Options(name="--in-file", forbids{"--table"})
String fileName;

@Option(name="--table", required=true, forbids={"--in-file"})
String table;

causes a logic error in that if I give --in-file it tries to forbid --table but it can't because --table is required.

So, the original solution fails because it allows the user to give neither option, even though I want --table' to be required, if and only if --in-file` is not given. So, basically, my original question.

So

Community
  • 1
  • 1
Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128
4

You can use forbids as you mentioned.

@Options(name="--in-file", forbids{"--table"})
String fileName;

@Option(name="--table", forbids={"--in-file"})
String table;

And you can add check-condition in your class.

if (fileName == null && table == null) {
    throw new CmdLineException();
}

You can set exception message same with message shown when required option set.

  • 1
    That's the cleanest idea I've seen so far. I just wish it was possible using only args4j syntax. I guess we can't always get what we want. – Matthew Herbst Oct 22 '15 at 21:26
  • How would you provide a message that way using non-deprecated CmdLineException ctors? – Novaterata Aug 11 '17 at 15:09
  • @Novaterata You can print usage on your own, ref: CmdLineParser::printUsage – Azeroth2b Jun 15 '22 at 15:52
  • 1
    @Azeroth2b I meant specifically how to pass a message to the CmdLineException constructor as you would with most Exceptions in my experience. I barely remember the context of this question, but I know that that Exception type had deprecated all of the obvious contructors – Novaterata Jun 15 '22 at 18:00