Args4j – CLI Parser (Command Line Interface Parser)

Args4j est un projet open-source, sous licence MIT, permettant de parser nos arguments/options de la ligne de commande. Le responsable du développement est Kohsuke Kawaguchi. Args4j est un sous-projet de Java Tools, qui est un ensemble de petits outils assez pratique pour tout développeur Java. On y trouve notamment Visual VM, pour monitorer notre VM, ou encore Hudson dont Kohsuke a forké le projet pour devenir Jenkins.

La manipulation d’arguments d’une application peut devenir vite contraignante quand il s’agit de les traiter comme des options.

En raison de sa simplicité et de sa taille (das le but de créer un uberJar), j’ai opté pour l’utilisation d’Args4j et ce, malgré la présence d’autres projets, tel que Commons CLI.

Je vais vous faire découvrir cette librairie à travers une explication détaillée. Vous trouverez les sources citées dans cet article sur mon github.

Pour commencer, on va créer une classe qui va nous permettre de déclarer toutes les options de notre application :

public class CommandLineOptions {
...
}

On va procéder à la déclaration de la première option dans notre application qui aura pour intérêt de définir obligatoirement un nom en tant qu’option.

@Option(name = "-n", usage = "Name of the application", metaVar = "String", aliases = "--name", required = true)
private String name;

La première chose que l’on puisse remarquer est l’utilisation d’annotation. Cela participe grandement à la lisibilité et la clarté de notre code mais cependant nécessite d’avoir au minimum un JRE en version 1.5.
Ainsi, nous avons déclaré notre attribut de type String de manière classique, qu’on a ensuite précéder de l’annotation @Option avec différents paramètres.
Voici une description de chacun de ces paramètres :

  • name : représente le nom de l’option
  • usage : permet de définir une description de l’option
  • metaVar : modifie le type affiché lors de l’affichage de l’utilisation de l’option
  • aliases : crée un alias au paramètre name, souvent utilisé pour définir des options avec un nom plus complet
  • required : comme son nom l’indique, permet d’indiquer si cette option est obligatoire (false par défaut)

Si l’option n’est pas obligatoire, il est possible de lui définir une valeur par défaut. Ceci en initialisant tout simplement notre attribut :

@Option(name = "-s", usage = "Override the default separator", aliases = "--separator")
private String separator = "\n";

Si nous devons également définir une liste ou autre collection, il suffit d’utiliser le paramètre multiValued sur notre annotation.

@Option(name = "-i", usage = "Number of integers", aliases = "--integer", multiValued = true)
private ListInteger› integers;

Voilà, nous avons vu quasiment tous les types de paramètre possible sur nos options. Un dernier point qui peut s’avérer très utile, Args4j va nous permettre de récupérer tous les arguments de notre programme dans une liste, grâce à l’annotation @Argument :

@Argument
private ListString› arguments;

Si nous voulions définir un nombre précis d’argument avec un ordre spécifique, il suffirait d’annoter chacun de nos attributs avec @Argument et de mettre le paramètre index :

@Argument(index = 0)
private String argument1;

@Argument(index = 1)
private String argument2;

( L’index commence bien-sur à 0 ;) )

Jusqu’ici, nous avons utilisé que des types de base, mais comment faire pour définir une option (ou argument) d’un type complexe ?

On crée tout d’abord une classe Complex.java, qui va représenter un nombre complexe dans notre cas.

public class Complex {
private int r, i;
...
}

Ensuite on déclare un attribut de type Complex et ajoutons parmi les paramètres de l’annotation un handler.

@Option(name = "-c", usage = "Definition of a complex type", aliases = "--complex", handler = ComplexHandler.class)
private Complex complex;

Ce handler va permettre de gérer la création de notre attribut à l’aide de la valeur passée à l’option. Pour cela, le handler doit hériter de la classe OptionHandler et ainsi implémenter les différentes méthodes nécessaires. La première est getDefaultMetaVariable() qui va permettre de définir, comme vu auparavant, le paramètre metaVar de notre option. Si le paramètre metaVar est défini sur l’annotation, alors sa valeur écrase la valeur du handler. La seconde méthode est parseArguments(String[]). Cette méthode va permettre de récupérer la valeur de l’option fournie en ligne de commande pour que l’on puisse effectuer le traitement dans cette méthode et créer notre attribut complexe.

Pour finir, on n’oublie pas les getters/setters. Apres quoi, nous pouvons passer au point d’entrée de l’application.

CommandLineOptions cliOpts = new CommandLineOptions();
CmdLineParser parser = new CmdLineParser(cliOpts);
try {
parser.parseArgument(args);
} catch (CmdLineException e) {
System.err.println(e.getMessage() + "\n");
parser.printUsage(System.err);
System.err.println("\n\tExample: Main " + parser.printExample(ALL));
System.exit(0);
}

Nous déclarons et instancions notre bean contenant toutes nos définitions d’options et arguments que l’on passe à un CmdLineParser. Ce parser va s’occuper de faire tout notre travail, il suffit d’appeler parseArgument(args). Si une option n’existe pas ou est mal formée, alors une exception sera levée et l’on affiche à l’utilisateur le manuel d’utilisation de l’application. Voici un exemple de ligne de commande correcte :

Main -d -i 1 -i 2 -c "1,2" --name MyApplication myArg1 myArg2

On remarque que pour utiliser l’option du type boolean il suffit juste de spécifier l’option suivi d’aucune valeur. Si on regarde dans le pom, on voit qu’on utilise actuellement la version 2.0.16 de Args4j, qui est la dernière version disponible sur le repository de Maven.

Depuis la version 2.0.19, Args4j permet de spécifier la valeur de notre option pour le type boolean. Avant la version 2.0.19, si une valeur était spécifiée pour une option de type boolean, alors cette valeur était prise comme argument de l’application. Pour ceux qui voudraient utiliser la version 2.0.19, vous devez rajouter le repository de Glassfish à votre pom.

‹repository›
‹id›glasshfish‹/id›
‹name›glassfish‹/name›
‹url›http://maven.glassfish.org/content/repositories/public‹/url›
‹/repository›

Enfin, lorsqu’on essaye de lancer cette application sans aucun argument (ou que nous faisons une erreur de saisie), on se retrouve avec un joli message d’explication ainsi que les différentes options possibles et un exemple d’utilisation :

1
2
3
4
5
6
7
8
9
Option "-n (--name)" is required

-c (--complex) "int r, int i": Definition of a complex type
-d (--display) : Display or not the configuration
-i (--integer) int : Number of integers
-n (--name) String : Name of the program
-s (--separator) String : Override the default character separator

Example: Main -c (--complex) "int r, int i"-d (--display) -i (--integer) int -n (--name) String-s (--separator) String

Voilà à peu près tout pour cette librairie assez sympa !

Vous trouverez les sources de cet article sur mon repository github.

VN:R_U [1.9.22_1171]
Rating: 0 (from 0 votes)
Share
Ce contenu a été publié dans Non classé, Outils, avec comme mot(s)-clef(s) . Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire