2013-01-13 20 views
6

Więc mam instancję Options która między innymi opcjami został (zawiadomienie isRequired()):Jak można uniknąć wyjątku ParserException dla wymaganych opcji, gdy użytkownik chce wydrukować tylko użycie?

 options.addOption(OptionBuilder 
       .withLongOpt("seq1") 
       .withDescription("REQUIRED : blah blah") 
       .hasArg().isRequired().create()); 
     options.addOption(OptionBuilder 
       .withLongOpt("seq2") 
       .withDescription("REQUIRED : blih blih") 
       .hasArg().isRequired().create()); 
     options.addOption(new Option("?", "help", false, 
       "print this message and exit")); 

Kiedy zadzwonić parser.parse(args) zgłasza wyjątek, jeśli seq1 i seq2 nie są obecne - ale chcę mieć go wydrukować moją wiadomość i nie ma wyjątku - jak to zrobić? To rzuca NPE w line.hasOption("help"), naturalnie:

CommandLine line = null; 
try { 
    CommandLineParser parser = new GnuParser(); 
    // parse the command line arguments 
    line = parser.parse(options, args); 
} catch (ParseException e) { 
    if (line.hasOption("help")) { //NPE 
     usage(0); 
    } 
    System.err.println("Parsing failed. Reason: " + e.getMessage()); 
    usage(1); 
} 

private static void usage(int exitCode) { 
    // automatically generate the help statement 
    HelpFormatter formatter = new HelpFormatter(); 
    formatter.printHelp("Smith Waterman", OPTIONS, true); 
    System.exit(exitCode); 
} 
+0

gdy parser.parse() zgłasza wyjątek ParseException, żadna wartość nie jest zwracana. Tak działają wyjątki java. Najprawdopodobniej będziesz musiał sam sprawdzić oryginalne argumenty, aby sprawdzić, czy opcja "pomoc" została zaliczona. – GreyBeardedGeek

+0

@GreyB: Wiem (zauważ, że _ _ _ _ __) - Jestem pewien, że musi istnieć inny sposób - w rzeczywistości znalazłem obejście, ale mam nadzieję, że odpowie na nie ktoś bardziej kompetentny - inaczej opiszę to jako odpowiedź –

Odpowiedz

7

Rozwiązanie dostosowane od here

private static final Options OPTIONS = new Options(); 
private static final Options HELP_OPTIONS = new Options(); 
OPTIONS.addOption(OptionBuilder 
     .withLongOpt("seq1") 
     .withArgName("file1") 
     .withDescription(
       "REQUIRED : the file containing sequence 1") 
     .hasArg().isRequired().create()); 
// etc 
final Option help = new Option("?", "help", false, 
     "print this message and exit"); 
HELP_OPTIONS.addOption(help); 
OPTIONS.addOption(help); 
// later 
CommandLineParser parser = new GnuParser(); 
CommandLine line = parser.parse(HELP_OPTIONS, args, true); // true so it 
// does not throw on unrecognized options 
if (line.hasOption("help")) { 
    usage(0); // calls exit 
} 
line = parser.parse(OPTIONS, args); 

Jeśli coś bardziej elegancki podchodzi Chętnie przyjmuję je

+0

To jakoś się nie udaje, gdy na końcu dodaje się '?' lub '--help'. 'command --seq1 --help' dałby mi' MissingArgumentException' Zrobiłem mały check przed analizą teraz – superbly

+0

@superbly: rozważ zgłoszenie go i opublikowanie linku z raportu tutaj –

+0

Dodałem odpowiedź z czekiem: http : //stackoverflow.com/a/28543094/606496 – superbly

0

Commons CLI nie obsługuje zależności między opcjami, jak to odkryli. W twoim przypadku opcja --help modyfikuje wymaganie dla seq1 i seq2.

Jedynym realnym rozwiązaniem jest uczynienie wszystkich opcji niewymaganymi i samodzielną weryfikację zależności po zakończeniu przetwarzania wiersza polecenia.

+0

Nieprawda - jest ale naprawdę nie jestem usatysfakcjonowany - opublikujemy go, jeśli nikt nie wymyśli czegoś bardziej eleganckiego. –

1

Może to być przydatne w zależności od sposobu użytkowania. Kopalnia jest w następujący sposób:

  • Mam jeden program otoki (zwany „kontrolera”)
  • istnieje wiele poleceń (zwane „zadania”), że kontroler może uruchomić
  • każde polecenie posiada własny zestaw unikalna linia poleceń argumentu ustawia

na przykład:

$ controller startall -rsrc foo -dir bar -where baz 

pierwszą rzeczą wykonanej z argumentami jest ustalenie, co to polecenie. W tym celu ustawiłem TaskFactory, który analizuje pierwszy argument, rozdziela wszelkie myślniki i sprawdza, czy jest to znane zadanie. Mam 'help', zadanie, które pozwala mój użytkownikowi zrobić:

$ controller -help 

i

$ controller help 

Każde zadanie posiada również opcję pomocy, tak więc użytkownik może zrobić:

$ controller startall -help 

To może jednak nie pomóc. Wezmę alternatywę.

0

Extend wybraną parser ignorować nieznane opcje:

Can Apache Commons CLI options parser ignore unknown command-line options?

A potem przeanalizować argumenty dwa razy, raz na -help argumentu i raz na normalnych argumentów. Za pierwszym razem powinieneś przekazać mu flagę "ignoruj", za drugim razem nie powinieneś.

Ewentualnie przeanalizuj opcje dwukrotnie, raz szukając -help i przechwytując (i ignorując) MissingOptionException, a następnie ponownie, stosując zwykłe argumenty.

1

użyłem następujące sprawdzić przed analizą, aby upewnić -h lub --help unieważnia wszystko inne.

// check if help is requested 
if (Arrays.asList(args).contains("-h") 
     || Arrays.asList(args).contains("--help")) { 
    usage(0); // print usage with exit 0 
} 
// parse options 

Nie najładniejsze rozwiązanie, ale służy moim potrzebom.

Powiązane problemy