2016-04-19 6 views
3

Если у меня есть 2 варианта, определенный в соответствии с требованиями, такими как:Apache CLI: Обязательные параметры противоречат с помощью опции справки.

public static void main(String [] args){ 
     Options options= new Options(); 
     Option inputFileOp=Option.builder("i").longOpt("input").hasArg().desc("Input file").argName("file").required().build(); 
     options.addOption(inputFileOp); 

     Option outputFileOp=Option.builder("o").longOpt("output").hasArg().desc("Output file").argName("file").required().build(); 
     options.addOption(outputFileOp); 

и помощью опционных

Option helpOp =new Option("h",false,"Show Help"); 
    helpOp.setLongOpt("help"); 
    helpOptions.addOption(helpOp); 

и парсер

DefaultParser parser = new DefaultParser(); 
CommandLine cmd=parser.parse(options,args); 

if(cmd.hasOption(helpOp.getOpt())){ 
     HelpFormatter formatter = new HelpFormatter(); 
     formatter.printHelp("MyApp.sh", options); 
     System.exit(0); 
    } 

} 

Когда пользовательский ввод, например MYAPP -h. На этапе анализа возникает исключение, при котором отсутствуют требуемые параметры, пока я хочу распечатать справочные данные.

Как разрешить вызов справки при сохранении указанных опций?

ответ

3

Код DefaultParser, как представляется, всегда вызывает метод checkRequiredArgs(). Который, кажется, указывает, что вы не можете одним махом избежать этой проблемы.

То, как мы рассматривали эту ситуацию в прошлом, возможно, неоптимально, состоит в том, чтобы анализировать командную строку дважды. Разбор выполняется быстро, поэтому накладные расходы минимальны.

Мы создали метод checkForHelp(String[] args), который принимает (String [] args). Он добавляет только параметр справки к параметрам, анализирует командную строку, а затем выясняет, указана ли помощь. Если да, то справка печатается, и программа выходит. В противном случае обрабатывается полный набор параметров. Этот подход позволяет обрабатывать необходимые поля, как ожидалось. Обратите внимание, что параметр справки также должен быть добавлен в основной список.

public static Option helpOption = Option.builder("h") 
      .longOpt("help") 
      .required(false) 
      .hasArg(false) 
      .build(); 

    public static boolean checkForHelp(String[] args) throws ParseException { 
    boolean hasHelp = false; 

    Options options = new Options(); 


    try { 
     options.addOption(helpOption); 

     CommandLineParser parser = new DefaultParser(); 

     CommandLine cmd = parser.parse(options, args); 

     if (cmd.hasOption(helpOption.getOpt())) { 
      hasHelp = true; 
     } 

    } 
    catch (ParseException e) { 
     throw e; 
    } 

    return hasHelp; 
    } 

Тогда в main метод, что-то похожее на:

options.addOption(hostOption); 
    options.addOption(portOption); 
    options.addOption(serviceNameOption); 
    options.addOption(helpOption); // <-- must also be here to avoid exception 

    try { 
     if (checkForHelp(args)) { 
      HelpFormatter fmt = new HelpFormatter(); 
      fmt.printHelp("Help", options); 
      return; 
     } 

     CommandLineParser parser = new DefaultParser(); 
     CommandLine cmd = parser.parse(options, args); 


     if (cmd.hasOption("host")) { 
      host = cmd.getOptionValue("host"); 
      System.out.println(host); // gets in here but prints null 
     } 
     if (cmd.hasOption("port")) { 
      port = ((Number) cmd.getParsedOptionValue("port")).intValue(); 
      System.out.println(port); // gets in here but throws a null 
             // pointer exception 

     } 
     if (cmd.hasOption("service_name")) { 
      serviceName = cmd.getOptionValue("service_name"); 
      System.out.println(serviceName); // gets in here but prints null 
     } 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 

EDIT: как выясняется, этот подход аналогичен ответу, предоставленной здесь: Commons CLI required groups. Думаю, мне лучше, что в нашем подходе есть другие, поддерживающие то, во что мы верили.

EDIT2: В быстрой проверке, я считаю, что проблему с наличием необходимых параметров можно избежать, используя «OptionGroup». Вот пересмотренный checkForHelp, который работает, добавив все опции в OptionGroup. В моем быстром тестировании он избегает проблемы, которая присутствовала, например, («--arg1 --help»).

public static boolean checkForHelp(String[] args) throws ParseException 
{ 
    boolean hasHelp = false; 

    Options options = new Options(); 


    try { 
     options.addOption(hostOption); //has required set 
     options.addOption(portOption); 
     options.addOption(serviceNameOption); 
     options.addOption(helpOption);    

     // create an option group 
     OptionGroup og = new OptionGroup(); 
     og.addOption(hostOption); 
     og.addOption(portOption); 
     og.addOption(serviceNameOption); 
     og.addOption(helpOption); 

     CommandLineParser parser = new DefaultParser(); 

     CommandLine cmd = parser.parse(options, args, false); 

     if (cmd.hasOption(helpOption.getOpt()) || cmd.hasOption(helpOption.getLongOpt())) { 
      hasHelp = true; 
     } 

    } 
    catch (ParseException e) { 
     throw e; 
    } 

    return hasHelp; 
} 
+0

Спасибо за ответ. На самом деле, я уже пробовал это раньше, несмотря на то, что это выглядит как взломать больше, чем формальный способ :(. Тем не менее проблема заключается в том, что у вас есть объект-параметр только с помощью справки, другие параметры будут генерировать исключение исключенной опции. –

+0

Благодарим вас за редактирование и указатель я не мог дотянуться до него, когда искал.В ответах на комментарии они жалуются, что проблемы могут возникнуть из-за наличия двух разных групп опций. –

+0

@ MohamedGad-Elrab. Верно, что другие значения могут создать эту ситуацию. Однако посмотрите [здесь] (http://stackoverflow.com/questions/6049470/can-apache-commons-cli-options-parser-ignore-unknown-command-line-options) для быстрого способа потенциально решить нераспознанные аргумент исключение. – KevinO

0

Добавить другой метод, как сказал предыдущий плакат, но убедитесь, что вы остановились при первом непризнанном аргументе.

private static boolean hasHelp(final Option help, final String[] args) throws ParseException 
{ 
    Options options = new Options(); 
    options.addOption(help); 
    CommandLineParser parser = new DefaultParser(); 
    CommandLine cmd = parser.parse(options, args, true); 
    return cmd.hasOption(help.getOpt()); 
} 

Если stopAtNonOption установлено значение ложно, то эта функция будет забросить действительных аргументов, как java -jar app.jar -doStuff