Support us

Динамические выражения в приложениях на базе Eclipse RCP

Оставить комментарий
Динамические выражения в приложениях на базе Eclipse RCP
Задача: разработать удобный механизм, позволяющий вводить и изменять выражения на специальном языке и получать результат их выполнения в любом месте приложения. Выражения вводятся, изменяются и вычисляются «на лету» без компиляции и остановок приложения. Данная задача, безусловно, может очень часто встречаться в самых разных бизнес-приложениях:
  • расчет показателей на основе часто меняющихся данных (котировки акций, коэффициенты ставок и т.д.)
  • разнообразные преобразования данных из одного представления в другое
  • расчет параметров на основе введенных пользователем данных
  • и т.п.
К примеру, на моем текущем проекте динамические выражения используются для расчета цены заказа на основе выбранных пользователем продуктов и их параметров, автоматическая коррекция заказа, преобразование данных заказа для записи в файл Excel. Есть предчувствие, что это еще далеко не все и механизм будет использоваться в будущем для решения других проблем. Итак, расскажу как это устроено и работает у нас. Предполагается, что читатель знаком с разработкой приложений на базе Eclipse RCP. Наш проект представляет собой клиент-серверную систему, где клиентское приложение построено на базе платформы Eclipse RCP. Кроме того, у нас уже использовался BIRT для построения различных отчетов. Исходя из этих предпосылок, было решено использовать именно возможности данного проекта для решения задачи. Выражения в нем представляют собой сценарии на языке JavaScript, т.е. имеется поддержка большинства функций и возможностей данного языка. Кроме того, стандартные функции JavaScript можно дополнить своими собственными и это немаловажно.

Ввод и редактирование выражений

Выражения можно вводить прямо в приложении используя специальный редактор из платформы BIRT (см. картинку). Редактор выражений birt Как видно, ребята из проектной группы BIRT постарались облегчить ввод сценариев на JavaScript для непрофессионалов. Есть три основных категории функций, которые выполняют функцию справочника и позволяют добавлять функции в пару кликов мышкой. Если бы добавить сюда автоматическое форматирование кода и средства навигации - цены бы не было этому редактору. А так - на больших выражениях придется помучиться, неудобно. Как хранить введенные таким образом выражения - решать вам. Важно только то, что на исполнении они должны представлять из себя строку (java.lang.String).

Собственные функции

Как уже писалось выше есть возможность определять собственные функции для использования внутри выражений. Они будут добавляться в категорию «Функции BIRT». Сделать это проще простого. Для начала нужно расширить extension-point org.eclipse.birt.core.ScriptFunctionService и описать новую функцию в plugin.xml:
  1.   <extension point="org.eclipse.birt.core.ScriptFunctionService"
  2.     id="extension_id"
  3.     name="Extension_Name">
  4.     <Category
  5.       desc="category description"
  6.       factoryclass="foo.bar.TestFunctionFactory"
  7.       name="CategoryName">
  8.       <Function
  9.         desc="function description"
  10.         name="myBirtFunction">
  11.         <DataType value="Object"/>
  12.         <Argument name="param1">
  13.           <DataType value="String"/>
  14.         </Argument>
  15.         <Argument name="param2">
  16.           <DataType value="Integer"/>
  17.         </Argument>
  18.         </Function>
  19.       </Category>
  20.   </extension>
Наша новая функция называется myBirtFunction и расположена в категории CategoryName. Данная категория появится в редакторе выражений как подкатегория «Функций BIRT». Как видим, принимает она два параметра: строку и число; и возвращает тип Object (т.е. что угодно). Вообще говоря, данное описание типа параметров и возвращаемого значения никак не влияет на интерпретацию вашей функции в BIRT. Т.е. вы можете запросто передать и возвратить параметры других типов. Более того, вы даже можете передать другое число параметров. Описание в XML используется для представления вашей функции в справочнике редактора выражений. Конечно, желательно чтобы описание функции совпадало с ее реальным поведением :) Итак, наша функция уже появилась в редакторе выражений, но она, конечно же, ничего не делает. Опишем ее внутренности. Можно заметить, что кроме описания функции в extension задается атрибут factoryclass (строка 6). Он указывает на реализацию интерфейса org.eclipse.birt.core.script.functionservice.IScriptFunctionFactory и его единственная задача - создать объект, который и будет представлять собой реализацию нашей новой функции. Этот объект, в свою очередь, является реализацией интерфейса org.eclipse.birt.core.script.functionservice.IScriptFunctionExecutor с единственным методом Object execute(Object[] args). Глядя на параметры этого метода становится понятно, почему описание функции в plugin.xml никак не влияет на реальный набор и тип параметров и возвращаемых значений. Таким образом, вся ответственность за их соблюдение ложится на программиста. Простейшие примеры реализации:
  1. public class SampleFunctionFactory implements IScriptFunctionFactory{
  2.  
  3.   @Override
  4.   public IScriptFunctionExecutor getFunctionExecutor(String functionName)
  5.       throws BirtException {
  6.     
  7.     if ("myBirtFunction".equals(functionName)){
  8.       
  9.       return new MyBirtFunctionExecutor();
  10.       
  11.     }
  12.     
  13.     return null;
  14.   }
  15.   
  16. }
  1.   public class MyBirtFunctionExecutor implements IScriptFunctionExecutor{
  2.  
  3.     @Override
  4.     public Object execute(Object[] args) throws BirtException {
  5.       
  6.       if (args.length == 2
  7.           && args[0] instanceof String
  8.           && args[1] instanceof Integer){
  9.         
  10.         return "Hello, world!";
  11.         
  12.       }
  13.       
  14.       return null;
  15.     }
  16.     
  17.   }
Итак, наша функция готова поприветствовать весь мир. Осталось ее вызвать и интерпретировать.

Выполнение выражений

Без лишних предисловий приведу код для выполнения выражений. Он довольно компактный:
  1.   ExecutionContext context = new ExecutionContext();
  2.   try {
  3.     IReportContext reportContext = new ReportContextImpl(context);
  4.     context.setReportContext(reportContext);
  5.     context.getScriptContext().registerBean("context"someObject);
  6.     // hack with classloader
  7.     context.setApplicationClassLoader(new ClassLoaderExtension(getClassLoader()));
  8.     return context.evaluate(expression);
  9.  
  10.   } catch (BirtException e) {
  11.  
  12.   }finally{
  13.     context.unregisterBean("context");
  14.   }
Теперь о его содержании. ExecutionContext - контекст выполнения выражения, экземпляр класса org.eclipse.birt.report.engine.executor.ExecutionContext. Именно он и выполняет (execute) выражение в строковом виде (expression) на строке 8. Интерпретация происходит с помощью движка Rhino от Mozilla. Кроме того, обратите внимание на небольшой хак с classloader'ом (строка 7). Кроме того, нашему контексту выполнения нужен IReportContext. Никаких проблем, нужен - значит нужен (строки 3-4). Отдельно обратите внимание на строки 5 и 13. Мы передаем контексту исполнения дополнительный контекст, который является нашей собственной реализацией и предназначен для возможности передачи объекта внутрь собственных функций. В этом случае при вызове функций в редакторе выражений нужно передавать параметр с именем context (как зарегистрировано) и конечно же желательно его описать в plugin.xml. Вот, пожалуй, и все. Исполняем выражение, которое вызывает нашу функцию, и получаем результат - «Hello, world!»

Заключение

По моему мнению BIRT дает довольно удобное средство для поддержки динамических выражений. Конечно, человек, который вводит выражения, должен знать хотя бы самые базовые основы программирования. Но, в любом случае, для ввода сложных выражений с разветвленной логикой эти основы знать придется, даже если ввод осуществляется исключительно с помощью компонентов GUI. Всю полностью платформу BIRT использовать при этом необязательно. Она довольна большая и тяжелая. По моим наблюдениям, достаточно использовать следующие ее части:
  • org.eclipse.birt.core
  • org.eclipse.birt.data
  • org.eclipse.birt.report.engine
  • org.eclipse.birt.report.designer.core;
  • org.eclipse.birt.report.designer.ui;
  • org.eclipse.birt.report.model;
  • org.eclipse.birt.report.data.adapter
  • org.eclipse.birt.report.model.adapter
  • org.mozilla.rhino
Все приведенные примеры работают на версии BIRT 2.3.1 (версия плагина с rhino1.6.7.r22x). Сейчас самая новая версия 2.6. Возможно, в ней будут некоторые отличия. Удачных разработок! Ссылка на оригинал: http://www.grodnosoft.by/2010/09/dinamicheskie-vyrajenija-v-eclipse.html Полезные ссылки:
Место солидарности беларусского ИТ-комьюнити

Далучайся!

Читайте также
Google запустила SDK для создания приложений, которые будут работать на разных устройствах и ОС
Google запустила SDK для создания приложений, которые будут работать на разных устройствах и ОС
Google запустила SDK для создания приложений, которые будут работать на разных устройствах и ОС
Как зарабатывать на приложениях с нуля. Опыт фрилансера с 10-летним стажем
Как зарабатывать на приложениях с нуля. Опыт фрилансера с 10-летним стажем
Как зарабатывать на приложениях с нуля. Опыт фрилансера с 10-летним стажем
Разработка мобильных приложений сегодня одно из самых перспективных и востребованных направлений в сфере IT. Пользователи в этой нише тратят в среднем 57,6 миллиардов долларов в год, а к 2025 году по оценкам PricewaterhouseCoopers (PWC) эта цифра вырастет до 335 миллиардов долларов.  Но легко ли сегодня фрилансеру зарабатывать на аппах с нуля?  Соло разработчик из Беларуси Алексей, разместивший на маркете свои первые приложения больше десяти лет назад, уверен, что с каждым годом это сделать сложнее. 
3 комментария
Amazon представила новый сервис малокодовой разработки Amplify Studio
Amazon представила новый сервис малокодовой разработки Amplify Studio
Amazon представила новый сервис малокодовой разработки Amplify Studio
2 комментария
Zoom выпустил SDK для интеграции видео в приложения
Zoom выпустил SDK для интеграции видео в приложения
Zoom выпустил SDK для интеграции видео в приложения

Хотите сообщить важную новость? Пишите в Telegram-бот

Главные события и полезные ссылки в нашем Telegram-канале

Обсуждение
Комментируйте без ограничений

Релоцировались? Теперь вы можете комментировать без верификации аккаунта.

Комментариев пока нет.