JYaml в качестве DSL

13 апреля 2007

Есть вот такая вот интересная задачка: приложение должно выполнять серию команд, внешне даже однотипных и настраиваемых через разные параметры. При этом описание очереди команд должно быть не в коде, а во внешнем файле, который можно отредактировать, и, без перекомпиляции приложения, запустить очередь заново. Да и вообще файл со списком команд указывать каким то параметром приложению, т.к. будут различные файлы с разными очередностями команд.

Этакий файл с описание фильтров для обрабатываемой информации, который редактируют не обязательно программисты.
Как варианты для реализации: придумать какой то свой формат, потом его интерпретировать. Но такой интерпретатор та еще задача, кучу времени потребует. Еще можно воспользоваться XML, из которого через Castor, к примеру, воссоздавать все наши объекты / фильтры / команды. Но вот какого объёма будет требуемый нам файл с описанием, страшно представить.
Ну а так как это получается некий узкоспециализированный язык, то я вот и предложу как упростить эту задачу. Идея растет из того же XML, но в более упрощённом виде, в виде YAML описания.
Итак, нам, к примеру, надо следующие команды:

  • замена в определённом поле
  • удаление по определённому регекспу
  • сортировка
  • удаление пробелов

Получаем вот такой вот файлик:

--- !replace
from: __UNKNOWN__
to: Computer
atField: author
--- !remove
regex: [^\\d]+
atFields:
  - year
  - phone
--- !sort
withComparator: !defaultComparator
  direction: desc
--- !transform
withTransformer: !trim{}

Этакий Domain Specific Language получается. Может на первый взгляд не так все просто, но если написать небольшое описание синтаксиса нашего языка, или знакомство с документацией по yaml, все встанет на свои места, и редактирование подобного списка команд становится несложной задачей, с которой может справится продвинутый пользователь. В общем я сейчас сильно в синтаксис не буду вдаваться, кому надо глянут на yaml.org и jyaml.sourceforge.net
Второй момент как это прочитать, т.е. как построить их этого файла наши объекты. Делается все просто, через упомянутый JYaml:

List<Command> list = new ArrayList<Command>();
YamlDecoder dec = new YamlDecoder(in);
try {
    while (true) {
        Command command = (Command) dec.readObject();
        list.add(command);
    }
} catch (EOFException e) {
    log.debug("Finished reading stream.");
} finally {
    dec.close();
}

ну и т.к. в файле мы использовали не полный имена классов, то надо настроить связь между именем и самим классом, это нужно сделать до чтения самих объектов, следующим образом:

BiDirectionalMap<String, String> classes = new BiDirectionalMap<String, String>();
classes.put("replace", ReplaceCmd.class.getName());
classes.put("remove", RemoveCmd.class.getName());
classes.put("trim", Trim.class.getName());
classes.put("sort", SortCmd.class.getName());
classes.put("defaultComparator", DefaultComparatorCmd.class.getName());
classes.put("transform", TransformCmd.class.getName());
YamlConfig.getDefaultConfig().setTransfers(classes);

На самом деле можно такой мини язык делать не только для списка команд, в общем то почти любой класс так можно описать и десериализовать после в объект, а текущая задача она применима к моим условиям. Правда тут возникла проблема: хотелось бы чтобы эти объекты помимо описания в этом файле имели настройки в Spring. Т.е. все связи с другими объектами настроить в Spring контексте, а саму очерёдность и дополнительные настройки брать уже из этого файла. Так вот это я не знаю как реализовать, не расширяя YamlDecoder. Хотя, т.к. jyaml проект open source’ный, это тоже вполне реализуемо.

2 Комментариев на “JYaml в качестве DSL”

  1. xeye сказал:

    для этого существует груви :)

  2. igor сказал:

    Согласен :) Ну и jruby тоже неплох.

Оставьте свое мнение

XHTML: Вы можете использовать следующие html теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> Если в комментарии пишете XML то вместо "<" используйте "&lt;"

Благодарности, комментарии не по теме и пр. спам ссылками удаляется, к тому же автоматически, можете не стараться.