jcommander
                                
                                
                                
                                    jcommander copied to clipboard
                            
                            
                            
                        Using commands feels a bit awkward at the moment
Using commands isn't as easy as the rest of JCommander.
I have code that looks like this:
    CommandLineArgs cl=new CommandLineArgs();
    JCommander commander = new JCommander(cl);
    Cat cat = new Cat();
    commander.addCommand(Cat.NAME, cat);
    Tail tail = new Tail();
    commander.addCommand(Tail.NAME, tail);
    Index index = new Index();
    commander.addCommand(Index.NAME, index);
The thing that's bugging me is that I had to define a public static final NAME field in each of my command instead of annotating the class, simply calling
    addCommand(command)
The same is the case for using the command:
    String command = commander.getParsedCommand();
    if(Tail.NAME.equals(command)) {
        [...]
    }
So there are two places where I still need to juggle with plain strings. Instead, I'd like to have something like
    Object commandObject = commander.getParsedCommandObject();
This would be really useful if all registered command objects would implement the same interface, e.g. Runnable. In that case, I could simply cast the returned commandObject and call run() (after checking against null, obviously).
This functionality could even be wrapped into the getParsedCommandObject() method like this:
    Runnable commandObject = commander.getParsedCommandObject<Runnable.class>();
                                    
                                    
                                    
                                
I agree that commands are kinda uneasy to use.
I do like the commandName and commandAliases in @Parameters annotation.
I was also trying to get commands to work with enums. Here's some (maybe weird) code: Commands@aeea04.
It'd be nice if I could set @Parameters (and not just @Parameter) to each enum element, so I could specify the command description.
The above as it is, results to this:
$ java -jar dist/test.jar --help
Usage: app.Fic [options] [command] [command options]
  Options:
    -d, --debug    display debug messages
                   Default: false
  [...]
  Commands:
    compress     compress and decompress commands
    decompress   compress and decompress commands
$ java -jar dist/test.jar --help compress
compress and decompress commands
Usage: compress [options]
  Options:
  * -i, --input    the input file
    -o, --output   the output file
                                    
                                    
                                    
                                
I think using enums for commands is a brilliant idea. Adding annotations to enums does not seem very clean though, but I think it should be easy to extend addCommand(String, Object) interface to support addCommand(Enum<?>, Object) and then have a Enum<?> getParsedCommandEnum().
You have inspired my for another good idea: How about a addCommand(Object) method, that would automatically create command name from the class name. So for example:
class Commit{
  //parameter definitions here
}
//... main ...
// work out command name from class name => "commit"
jc.addCommand(new Commit());
if("commit".equals(jc.getParsedCommand()){
  //go
}
or even
if(Commit.class == jc.getParsedCommandClass()){
  //go
}
When using the later, you can avoid declaring extra enums or string constants, and at the same time keep your code refactoring-proof.
@cbeust an old one but some nice thoughts about Commands in it.
What do you say?
Yes, I agree, lot of good ideas here. I'll go over it and think about how to improve the design of commands, let's keep this open.
In the last project I used JCommander in (not very recently), I used Enums to wrap all my command classes. Each Enum had two fields: a String to hold the command name and a Class<?> to hold the corresponding class type of the command. This approach helped me work around the problem @huxi described with an utility like getEnum from Apache Commons.
As @cbeust thinks we had good ideas here, wouldn't it be cool if someone of us would open a PR? 8-)