Статьи

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

В первых двух статьях этой серии, посвященных анализу командной строки в Java , я рассмотрел библиотеки Apache Commons CLI и args4j . В этом третьем посте из серии я расскажу о jbock , самоописанном «любопытно простом парсере CLI».

В моих статьях о разборе командной строки в Java использовались примеры, основанные на предоставлении требуемого имени файла и необязательного подробного флага для приложения Java. Тот же подход используется в этом посте для демонстрации jbock 1.8 . Полный исходный код для примера класса доступен на GitHub , но код, сгенерированный jbock ( Main_Parser ), недоступен, так как он может быть сгенерирован.

Подход, который jbock использует для обработки в командной строке, отличается от того, который используется двумя ранее описанными библиотеками синтаксического анализа. Ранее рассмотренные библиотеки требовали, чтобы Java-код для анализа аргументов командной строки создавался и выполнялся для библиотек JAR. Другими словами, JAR-файлы библиотек должны находиться как на пути к классам во время компиляции ( javac ), так и на пути к классам запуска Java во время выполнения ( java ). Вместо этого подход jbock опирается на включение JAR-файла jbock только во время компиляции. Подход jbock генерирует исходный код Java, который полностью независим от библиотеки jbock. Можно, например, выбрать запуск jbock, чтобы сгенерировать эти файлы исходного кода Java один раз, а затем управлять версиями этих сгенерированных файлов и с этого момента создавать и запускать только сгенерированные файлы без необходимости создавать или запускать JAR-файл jbock. Единственный раз, когда требуется JAR-файл jbock, — это когда сгенерированный исходный код Java необходимо восстановить. Поскольку сгенерированный код генерируется на основе аннотаций для пользовательских классов Java, вполне вероятно, что генерация кода jbock будет выполняться в большинстве случаев как часть обычной сборки, а не как версия, управляющая сгенерированным источником.

В большинстве случаев я бы использовал пользовательский класс с именем, например « Arguments » или « CommandLine », при использовании jbock для разбора аргументов командной строки. Однако в этом посте я использую простой класс Main чтобы он был более похож на пример с подходом, используемым с другими библиотеками синтаксического анализа командной строки в других статьях этой серии. Как и args4j, jbock использует аннотации для фазы «определения» обработки командной строки. Однако аннотации jbock относятся к конструктору класса и его аргументам, а не к подходу args4j по аннотированию полей класса. Подход аннотаций на основе конструктора jbock продемонстрирован в следующем листинге кода.

jbock «Определение» параметров командной строки

01
02
03
04
05
06
07
08
09
10
11
@CommandLineArguments
public Main(
   @ShortName('v') @LongName("verbose") @Description("Verbosity enabled?")
   final boolean newVerbose,
   @ShortName('f') @LongName("file") @Description("File name and path")
   final Optional<String> newFileName)
{
   verbose = newVerbose;
   file = newFileName.orElse("");
}
// . . .

Этап «синтаксического анализа» обработки командной строки с помощью jbock продемонстрирован в следующем листинге кода.

Параметры синтаксического анализа в командной строке с помощью jbock

1
2
3
final Main_Parser parser = new Main_Parser();
final Main_Parser.Binder binder = parser.parse(arguments);
final Main main = binder.bind();

Класс Main_Parser показанный в приведенном выше листинге кода, генерируется jbock на основе аннотаций, показанных в первом листинге кода. Библиотека jbock обрабатывает аннотации класса Main чтобы определить, как создать класс Main_Parser . Имя сгенерированного класса основано на имени класса с аннотациями jbock и объединено с _Parser . Например, если бы мой класс с аргументами конструктора jbock и аргументов конструктора был назван « Arguments », сгенерированный класс был бы назван « Arguments_Parser ».

После того, как экземпляр сгенерированного класса Main_Parser parse аргументов командной строки, вызывается метод bind() этого экземпляра для возврата экземпляра исходного аннотированного класса Main . Процесс «опроса» на этом этапе состоит исключительно из доступа к атрибутам этого экземпляра Main через его общедоступные методы «get». Это продемонстрировано в следующем листинге кода.

Этап «Опрос» обработки командной строки с помощью jbock

1
2
out.println("The file '" + main.getFile() + "' was provided and verbosity is set to '"
   + main.isVerbose() + "'.");

На приведенном ниже снимке экрана показан код в действии, использующий jbock для анализа параметров командной строки.

Если требуется помощь или информация об использовании, ее также можно получить из сгенерированного *_Parser (в данном случае Main_Parser ). В частности, сгенерированный класс *_Parser включает вложенное перечисление Option представляющее различные опции. Можно перебрать значения перечисления этих опций, чтобы получить метаданные о каждой опции. В приведенном ниже листинге кода метод description describe(int) вызывается для значения перечисления каждого параметра (переданное целое число — это число пробелов для отступа).

Получение сведений об использовании с помощью jbock

1
2
3
4
5
6
7
8
9
final Main_Parser parser = new Main_Parser();
if (arguments.length < 1)
{
   for (final Main_Parser.Option option : Main_Parser.Option.values())
   {
      out.println(option.describe(3));
   }
   System.exit(-1);
}

Снимок экрана, показанный ниже, демонстрирует этот код в действии, чтобы распечатать параметры и их описания.

Исходный код, обсуждаемый в этом посте, доступен на GitHub .

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

  • Jbock доступен с открытым исходным кодом .
  • Текущая версия jbock (1.8) требует Java SE 8 .
  • У jbock нет сторонних или внешних зависимостей.
  • JAR jbock-1.8.jar jbock 1.8 ( jbock-1.8.jar ) имеет размер приблизительно 131 КБ, но это не так важно, как для аналогичных библиотек, поскольку этот JAR jbock-1.8.jar не требуется во время выполнения (сгенерированный код не зависит от JAR-файла).
  • Я не демонстрировал применение jbock наличия обязательных параметров командной строки, потому что он намеренно не поддерживает эту функцию. README заявляет: «Умышленно просто: нет конвертеров, значений по умолчанию или обязательной проверки . С java 8 легко добавить этот материал вручную ».

Наиболее очевидной характеристикой jbock, которая отличает его от большинства других библиотек синтаксического анализа на основе Java, является генерация кода синтаксического анализа полностью во время компиляции, которая не оставляет зависимостей времени выполнения от библиотеки jbock. Это было бы очевидным преимуществом в ситуациях, когда существует проблема с количеством загруженных классов или размером выраженного пути к классам. В README перечислены несколько элементов, которые «выделяют [jbock] отдельно». К ним относятся «без отражения, чисто статический анализ» и «удобное, гибкое связывание свойств с помощью конструктора».