Статьи

Интерфейсы командной строки Java (часть 25): JCommando

JCommando описывается на сайте JCommando как «анализатор аргументов Java для параметров командной строки». JCommando читает конфигурацию XML, чтобы сгенерировать класс Java, который обрабатывает анализ из приложения Java. Единственная библиотека на основе Java, ранее рассмотренная в этой серии публикаций по библиотекам синтаксического анализа командной строки Java, которая предоставляла конфигурацию XML, — это JSAP , но это вторичная форма конфигурации с этой библиотекой, и я не рассматривал конфигурацию XML в своем посте на JSAP .

Поскольку JCommando использует XML для указания параметров командной строки, которые нужно проанализировать, этап «определения» с помощью JCommando выполняется через спецификацию XML. Как и в предыдущих статьях этой серии , примеры в этой статье основаны на параметрах командной строки для пути к файлу, имени и многословности, а их определение в XML, совместимом с JCommando, показано в следующем листинге кода ( options.xml ).

JCommando через XML-часть этапа «Определение»: options.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
<jcommando>
   <option id="file" long="file" short="f" type="String">
      <description>Path and name of file</description>
   </option>
   <option id="verbose" long="verbose" short="v">
      <description>Verbosity enabled</description>
   </option>
   <commandless id="execute" allow-optionless="true">
      <or>
         <option-ref id="file" />
      </or>
   </commandless>
</jcommando>

JCommando использует входной файл XML и на основе этого XML создает файл исходного кода Java, который анализирует параметры, указанные в XML. Есть два способа проинструктировать JCommando для анализа этого XML и использования деталей для генерации исходного кода Java. Одним из способов является использование исполняемого файла jcomgen, поставляемого с дистрибутивом JCommando (в его каталоге bin ). Второй подход для генерации Java-класса из XML — это подход, показанный здесь: использование Apache Ant и поставляемая JCommando задача Ant. Это продемонстрировано в следующем листинге XML / Ant.

Цель Ant для генерации исходного кода из XML с помощью JCommando

01
02
03
04
05
06
07
08
09
10
11
12
13
<target name="generateSourceForJCommando"
          description="Generate command line parsing source code that uses JCommando">
    <taskdef name="jcommando" classname="org.jcommando.ant.JCommando">
      <classpath>
        <pathelement location="C:\lib\jcommando-1.2\lib\jcommando.jar"/>
      </classpath>
    </taskdef>
 
    <jcommando inputfile="jcommando/options.xml"
               classname="MainParser"
               destdir="src"
               packagename="examples.dustin.commandline.jcommando"/>
  </target>

Вышеуказанная цель Ant показывает, как JCommando позволяет указывать входной XML-файл ( options.xml ) в качестве « inputfile » и что сгенерированный файл исходного кода Java будет помещен в каталог src в структуре подкаталогов, соответствующей указанному пакету. « examples.dustin.commandline.jcommando «. Выполнение цели Ant и генерация исходного кода показаны на следующем снимке экрана.

Результатом этой цели Ant является сгенерированный исходный класс Java MainParser.java , список которого показан ниже.

Сгенерированный исходный класс Java MainParser.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * THIS IS A GENERATED FILE.  DO NOT EDIT.
 *
 */
 
package examples.dustin.commandline.jcommando;
 
import org.jcommando.Command;
import org.jcommando.JCommandParser;
import org.jcommando.Option;
import org.jcommando.Grouping;
import org.jcommando.And;
import org.jcommando.Or;
import org.jcommando.Xor;
import org.jcommando.Not;
 
/**
 * JCommando generated parser class.
 */
public abstract class MainParser extends JCommandParser
{
   /**
     * JCommando generated constructor.
     */
   public MainParser()
   {
      Option file = new Option();
      file.setId("file");
      file.setShortMnemonic("f");
      file.setLongMnemonic("file");
      file.setDescription("Path and name of file");
      addOption(file);
 
      Option verbose = new Option();
      verbose.setId("verbose");
      verbose.setShortMnemonic("v");
      verbose.setLongMnemonic("verbose");
      verbose.setDescription("Verbosity enabled");
      addOption(verbose);
 
      Command execute = new Command();
      execute.setName("commandless");
      execute.setId("execute");
      execute.addOption(file);
      execute.setGrouping( createExecuteGrouping() );
      addCommand(execute);
 
   }
 
   /**
     * Called by parser to set the 'file' property.
     *
     * @param file the value to set.
     */
   public abstract void setFile(String file);
 
   /**
     * Called by parser to set the 'verbose' property.
     *
     */
   public abstract void setVerbose();
 
   /**
     * Called by parser to perform the 'execute' command.
     *
     */
   public abstract void doExecute();
 
   /**
    * Generate the grouping for the 'execute' command.
    */
   private Grouping createExecuteGrouping()
   {
      Or or1 = new Or();
      or1.addOption(getOptionById("file"));
      return or1;
   }
}

Сгенерированный исходный код Java, теперь у нас есть наши определения опций. Пользовательский класс написан для расширения сгенерированного MainParser и доступа к его родительскому MainParser для анализа. Это продемонстрировано в следующем листинге кода специально написанного класса Main который расширяет сгенерированный класс MainParser .

Пользовательский класс, расширяющий сгенерированный класс

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package examples.dustin.commandline.jcommando;
 
import static java.lang.System.out;
 
/**
 * Demonstrates JCommando-based parsing of command-line
 * arguments from Java code.
 */
public class Main extends MainParser
{
   private String file;
   private boolean verbose;
 
   @Override
   public void setFile(final String newFilePathAndName)
   {
      file = newFilePathAndName;
   }
 
   @Override
   public void setVerbose()
   {
      verbose = true;
   }
 
   public static void main(final String[] arguments)
   {
      final Main instance = new Main();
      instance.parse(arguments);
   }
 
   /**
    * Called by parser to execute the 'command'.
    */
   public void doExecute()
   {
      out.println("File path/name is " + file + " and verbosity is " + verbose);
   }
}

Как показано в пользовательском исходном коде Main.java показанном выше, этап «синтаксического анализа» выполняется в JCommando посредством выполнения метода parse(String[]) унаследованного от класса, сгенерированного JCommando на основе XML конфигурации (и этого сгенерированного класса). получает определение этого метода parse из родительского класса JCommandParser ).

Пользовательский класс, который расширяет сгенерированный класс, необходимый для реализации методов «set» для опций. При их правильной реализации этап «опроса» в приложениях на основе JCommando так же прост, как и доступ к полям, установленным этими пользовательскими методами «set». Это было продемонстрировано в doExecute() показанном в последнем листинге кода. Этот метод doExecute был сгенерирован как abstract метод в сгенерированном родительском классе из-за спецификации элемента <commandless> с id « execute » в XML конфигурации.

Класс JCommandParser, который в конечном итоге расширяет пользовательский класс, имеет метод printUsage (), который можно использовать для записи вывода «help» / «using» в стандартный вывод. Это можно увидеть в исходном коде Main.java доступном на GitHub .

Следующие два снимка экрана демонстрируют выполнение примера кода, обсуждаемого в этом посте. Первый снимок экрана показывает «информацию об использовании, которая может быть автоматически напечатана, в этом случае, когда не была указана необходимая опция« файл ». На втором снимке экрана показаны комбинации длинных и коротких названий опций для «мерзких» и «подробных» опций.

Шаги, связанные с использованием JCommando, которые обсуждались в этом блоге, кратко изложены здесь.

  1. Определите параметры в файле XML.
  2. Генерация исходного кода анализатора Java из XML с использованием одного из двух подходов.
    • Используйте инструмент jcomgen в каталоге bin JCommando.
    • Используйте цель Ant с предоставленной JCommand задачей Ant, как показано в этом посте.
  3. Напишите класс Java, который расширяет сгенерированный класс анализатора.

Есть особенности JCommando, которые следует учитывать при выборе платформы или библиотеки, чтобы помочь с анализом командной строки в Java.

  • JCommando имеет открытый исходный код и доступен по лицензии zlib / libpng (Zlib) .
  • JAR- файл jcommando.jar имеет размер приблизительно 27 КБ и не имеет сторонних зависимостей.
  • Определение параметров в JCommando через XML — это другой подход, чем в других библиотеках, описанных в этой серии, но то, что я нахожу более интересным в определении параметров JCommando, — это легкая способность выражать отношения между параметрами, такими как «и», «или», «xor». », И вложенные комбинации этих.

JCommando реализует некоторые новые концепции с точки зрения анализа параметров командной строки на основе Java. Это требует XML-конфигурации потенциальных параметров командной строки, но позволяет легко устанавливать отношения между этими параметрами. JCommando генерирует исходный код Java из конфигурации параметров XML, а пользовательский класс синтаксического анализа расширяет этот сгенерированный класс. JCommando также является первой из библиотек этой серии, использующих лицензию Zlib .

Дополнительные ссылки

Опубликовано на Java Code Geeks с разрешения Дастина Маркса, партнера нашей программы JCG . См. Оригинальную статью здесь: Интерфейсы командной строки Java (часть 25): JCommando

Мнения, высказанные участниками Java Code Geeks, являются их собственными.