воскресенье, 7 июля 2013 г.

14й - практикум. Oracle ADF. Groovy как динамический язык. Часть 1

Вступление.
     Когда эволюция приложения продолжается без пере компиляции программы, переустановки - это замечательно, по сути получив программу, можно дальше развивать ее функциональность, поведение. Обычно этим занимаются прикладные программисты, аналитики. Примеров таких программ  много, например 1С, мне приходилось развивать механизм скрипта в Diasoft FA# - Delphi Script, еще ранее подключал к ядру системы - Microsoft Script Host (VBScript). Идея достаточна у всех одинакова - иметь развитой язык программирования и возможность взаимодействия с внутренней бизнес моделью данных и интерфейсом пользователя.
      В Java для это созданы все условия. В ADF уже подключен и используется динамический язык Groovy, он в основном используется в модели данных (BC - Business Components) в выражениях для полей, переменных запроса, сообщениях, но ни чего не мешает распространить его далее.


Попробую показать в этой части взаимодействие с Моделью данных и Bindings атрибутами из pageDef. Схема HR на Oracle XE.

В API Groovy есть много возможностей подключения этого механизма к своей программе и это делается просто. Вот один пример:

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import my.model.vo.AppModuleImpl;


public class ScriptHost
{
  private AppModuleImpl model;
  private AdfBindings adfBindings;
  private Binding binding;
  private GroovyShell shell;

  public ScriptHost(AppModuleImpl model, AdfBindings adfBindings)
  {
    super();    
    this.model = model;
    this.adfBindings = adfBindings;
    binding = new Binding();    
    // глобальная переменная - model  
    binding.setVariable("model", this.model);
    // глобальная переменная - bindings
    binding.setVariable("bindings", this.adfBindings);
    shell = new GroovyShell(binding);
  }
 
  public void evalScript(String script)
  {
    shell.evaluate(script);
  }
 

Создается  "Binding" объект, для глобальных переменных (объектов), заполняется, и затем он используется в "GroovyShell".

В своем примере для переменной "model"  я использую текущий "ApplicationModule", а для переменной "bindings" - объект предоставляющий доступ к "Bindings" текущей страницы.
Код из bean по подготовку к запуску:

public class MyBean
{
  public MyBean()
  {
    super();
  }

  private ScriptHost sc = null;
  private AdfBindings adfBindings = null;

  public void runScript(ActionEvent actionEvent)
  {
    AppModuleImpl am = (AppModuleImpl) ADFUtils.getApplicationModuleForDataControl("AppModuleDataControl");
    if (sc == null)
    {
      // создаем скрипт хост с переменными (AppModuleImpl, AdfBindings)
      adfBindings = new AdfBindings();
      sc = new ScriptHost(am, adfBindings);
    }
    ViewObjectImpl vo = am.getScriptsView1();
    Row row = vo.getCurrentRow();    
    // здесь хранится код Groovy
    sc.evalScript((String) row.getAttribute("Code"));
  }
}

Класс предоставляющий доступ к "Bindings":

public class AdfBindings
{
  public AdfBindings()
  {
    super();
  }
  
  
  public Object getAttrValue(String attributeName)
  {
    return ADFUtils.getBoundAttributeValue(attributeName);
  }
  
  public void setAttrValue(String attributeName, Object value)
  {
    ADFUtils.setBoundAttributeValue(attributeName, value);
  }

А вот и пример groovy кода. Изменение заработной платы вынесено в прикладной код. И его может менять прикладной разработчик, сохранять в БД и не привлекать для этого Java программиста и не переустанавливать программу!!!. Мне нравится :-)

def emp = model.getEmployeesView();
def row = emp.first();
while(row != null){      
     // println row.getAttribute('LastName');
     row.setAttribute('Salary', row.getAttribute('Salary') * bindings.getAttrValue('param1') ); 
     row  = emp.next();
}

Параметр "param1" размещен в Bindings:



В коде выделены глобальные объекты и обращение к ним.
Возможности по истине большие, вплоть до написания больших программ, но там уже используется не  "GroovyShell", а другой объект.   

Рисунок формы из примера


Источник:

A dynamic language for the Java platform
http://groovy.codehaus.org/

 Исходный код

DDL, DML:

-- Create table
create table SCRIPTS
(
  script_id NUMBER not null,
  name      VARCHAR2(100) not null,
  code      VARCHAR2(4000) not null
)
;
-- Create/Recreate primary, unique and foreign key constraints 
alter table SCRIPTS
  add constraint SCRIPTS_PK primary key (SCRIPT_ID)
;
 
insert into SCRIPTS (SCRIPT_ID, NAME, CODE)
values (1, 'calc', 'def emp = model.getEmployeesView();
def row = emp.first();
while(row != null){      
     println row.getAttribute(''LastName'');
     row.setAttribute(''Salary'', row.getAttribute(''Salary'') * bindings.getAttrValue(''param1'') ); 
     row  = emp.next();
}');

 

2 комментария: