JewelCLI – CLI Parser

1. Introduction

JewelCLI est une librairie de parsing de ligne de commandes sous licence Apache. Elle est peut constituer une alternative sérieuse à  d’autres librairies plus connues telles que Commons CLI ou encore Args4j.

2. Concepts généraux

Quelque soit la librairie utilisée, la procédure de parsing de ligne de commandes suit généralement trois étapes successives :

  • La définition des options;
  • L’analyse (parsing) des arguments;
  • L’interrogation ou l’exploitation des données.

Une librairie sera jugée selon la manière qu’elle implémente ces différentes étapes. D’autres éléments comme la gestion des erreurs ou l’affichage du menu d’aide peuvent être déterminant quant au choix d’une librairie donnée.

Nous verrons au travers de cet article les choix retenus par JewelCLI pour répondre à ces concepts généraux ainsi que les spécificités qu’elle propose.

3. Utilisation de JewelCLI

3.1 Définition des options

JewelCLI opte pour une définition déclarative des options : un “bean” annoté représente les différentes options qu’une ligne de commandes peut prendre. Cette solution requiert cependant l’utilisation d’une version de JDK supérieure ou égale à 1.5.

Voici à quoi peut ressembler la définition des options d’une ligne de commandes :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class CommandLine {

private boolean flag;
private EnumSaison saison;
private ListString› liste = new ArrayListString();
private UneClassAvecUnConstructeurDeParametreString reference;

@Option
public void setFlag(boolean flag) {
this.flag = flag;
}

@Option(shortName = "s", defaultToNull = true, description = "une saison")
public void setSaison(EnumSaison saison) {
this.saison = saison;
}

@Option(shortName = "l,t", longName = "list")
public void setListe(ListString› liste) {
this.liste = liste;
}

@Option(shortName = "r", defaultToNull = true, pattern = "[1-9][0-9]*")
public void setReference(UneClassAvecUnConstructeurDeParametreString reference) {
this.reference = reference;
}

...

L’annotation @Option permet de définir une option de ligne de commande. Elle doit être placée sur les “setters” des propriétés qui doivent correspondre à un des types suivants :

  • Types primitifs (ou wrappers correspondants);
  • Enum;
  • Classe avec un constructeur acceptant une chaine de caractères en paramètre;
  • Une liste d’éléments.

@Option accepte plusieurs attributs permettant d’affiner la configuration de l’option. Une description détaillée de ces attributs est consultable dans la documentation officielle de JewelCLI.

3.2 Analyse des arguments

Une fois les options définies, on peut alors parser les arguments de la manière suivante :

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
CommandLine cmd = new CommandLine();
Cli‹CommandLine› cli = null;
try {
cli = CliFactory.createCliUsingInstance(cmd);
cli.parseArguments(args);
//Do something with cmd
} catch (ArgumentValidationException e) {
e.printStackTrace();
System.err.println(cli.getHelpMessage());
}
}

Ici il n’y a rien de bien compliqué : un objet Cli‹CommandLine› crée par une CliFactory permet d’analyser les arguments. On notera qu’une ArgumentValidationException est lancée si une erreur survient lors l’analyse. Le menu d’aide (généré automatiquement par JewelCLI) est quant à lui accessible via l’objet Cli‹CommandLine›.

 3.3 Interrogation des données

Avec JewelCLI, l’interrogation des données est très simple car il suffit de manipuler directement l’instance du “bean” annoté (CommandLine dans notre exemple) et le tour est joué.

 4. Comparaison avec Arg4j

Les utilisateurs d’Arg4j ont surement du remarquer que JewelCLI présentait beaucoup de ressemblances avec Arg4j tant au niveau des choix de conception (utilisation d’annotations, etc.) qu’au niveau de la syntaxe. Cependant chacune de ces librairies possèdent des spécificités dont voici celles que j’ai retenues. Pour plus d’information concernant Args4j vous pouvez vous référer à l’article suivant : Args4j – CLI Parser.

4.1 Avantages d’Args4j sur JewelCLI

  • La notion de Handler : avec Arg4J la correspondance entre une chaine de caractères et une classe représentant une option est de la responsabilité d’un Handler alors que JewelCLI requiert que la classe en question possède un constructeur acceptant une chaine de caractères comme paramètre. La solution d’Args4j semble donc plus souple que celle proposée par JewelCLI car moins intrusive.

4.2 Avantages de JewelCLI sur Args4j

  • Possibilité de valider la valeur d’une option : le paramètre pattern de l’annotation@Option permet de définir une expression régulière pour valider la valeur d’une option. Args4j ne propose pas ce type de fonctionnalité mais rien n’empêche le client d’effectuer cette validation après l’analyse des arguments. Par conséquent, bien qu’intéressante, cette fonctionnalité n’est pas très décisive dans le choix entre les deux librairies.
  • Une gestion plus intuitive des options acceptant plusieurs valeurs : Considérons une option multi-valuée (pouvant accepter plusieurs valeurs). Le client utilisant Args4j devra alors répéter le libellé de l’option pour chaque valeur passée :
exectuable --liste toto --liste titi --liste tutu

alors que celui de JewelCLI utiliserait une syntaxe plus simple :

executable --liste toto titi tutu

De plus JewelCLI permet d’intervenir plus finement sur le nombre de valeurs que peut accepter une liste à travers les paramètres exactly, maximum, minimum de l’annotation @Option. Dans certains situations cela peut s’avérer très pratique.

  •  Enfin JewelCLI permet de définir les options (via les annotations) sur une interface et sur une classe concrète alors que Args4j ne permet que la deuxième alternative. Très honnêtement je ne trouve pas d’intérêt particulier à passer par une interface dans ce cas précis mais il me paraissait important de noter ce point.

 5. Conclusion

En conclusion, on peut dire que l’utilisation d’annotations pour définir les options d’une ligne de commandes contribue à en simplifier la gestion. Cette approche s’oppose à l’approche programmatique utilisée par d’autres librairies plus “anciennes” comme Commons CLI. Par ailleurs, bien que globalement semblable à Args4j, JewelCLI propose plus d’éléments de configuration et surtout une documentation plus étoffée.

 

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

2 réponses à JewelCLI – CLI Parser

  1. David Duponchel dit :

    La syntaxe utilisée par JewelCLI pour les listes me semble étrange : pour moi,

    1
    --liste toto titi tutu

    ne signifie qu’une chose : liste=toto tandis que titi et tutu sont des arguments. C’est en tout cas ce que je comprend de la doc POSIX et des extensions GNU. Heureusement, JewelCLI interprète correctement le “–” : écrire

    1
    executable --liste toto titi tutu -- argument1 argument2

    fonctionne (les arguments iront dans le champ

    1
    @Unparsed

    ).
    C’est néanmoins dommage d’ajouter une ambigüité inutile avec un espace comme séparateur alors que la virgule est utilisée depuis des décennies (exemple :

    1
    ps --format pid,comm,%cpu,%mem

    ).

    VN:R_U [1.9.22_1171]
    Rating: 0 (from 0 votes)
    • melkashef@excilys.com dit :

      Ta remarque est très pertinente. J’avais trouvé ça bizarre aussi qu’il utilise l’espace comme séparateur pour les options à valeurs multiples. Ceci étant dit, je la trouve quand même un peu mieux que celle employée par Args4j.

      VN:R_U [1.9.22_1171]
      Rating: 0 (from 0 votes)

Laisser un commentaire