воскресенье, 29 июля 2012 г.

Enumeration ListBox with GWT Editor framework

       Представим следующую ситуацию: вы разрабатываете GWT приложение и ваши сущности(domain entities - основные структурные строительные блоки любой системы) имеют поля в виде перечислений(Enum). Ваши Proxies/DTO также работают с полями в виде перечислений. Но когда данные приходят на клиентскую часть(UI), то виджет ListBox работает только со строковым(String) форматом и необходимо выполнить преобразования из enum в String, и наоборот из String в enum. Но было бы хорошо иметь такой виджет, который бы умел работать с enum как со строками. Также добавим виджету возможность связывания данных между бином и UI-полями. Это возможность доступна благодаря GWT Editor framework
     Для начала создадим список перечислений возможных значений статуса:
  1. public enum Status {
  2.     PROGRESS,
  3.     RESOLVED,
  4.     REOPENED,
  5.     CLOSED,
  6.     OPEN;
  7.     
  8.     @Override
  9.     public String toString() {
  10.         return name().toLowerCase();
  11.     }
  12. }
* This source code was highlighted with Source Code Highlighter.
     Создадим ListBox умеющий работать с перечислением как со строками. Для этого наследуем класс от ValueListBox, который реализует интрефейс IsEditor.
  1. public class EnumerationListBox<E extends Enum<E>> extends ValueListBox<E> {
  2.     public EnumerationListBox() {
  3.         super(new EnumerationRenderer<E>(), new EnumerationKeyProvider<E>());
  4.     }
  5.     
  6.     public EnumerationListBox(Class<E> clazz) {
  7.         this();
  8.         setAcceptableValues(Arrays.asList(clazz.getEnumConstants()));
  9.     }
  10. }
* This source code was highlighted with Source Code Highlighter.
     Также нам необходимо создать классы EnumerationRenderer(отвечает за отрисовку объекта определенного типа в строковой форме) и EnumerationKeyProvider(обеспечивает ключ для элемента списка).
  1. public class EnumerationRenderer<E extends Enum<E>> implements Renderer<E> {
  2.  
  3.     @Override
  4.     public String render(E object) {
  5.         return object == null ? "" : object.toString();
  6.     }
  7.     
  8.     @Override
  9.     public void render(E object, Appendable appendable) throws IOException {
  10.         appendable.append(render(object));
  11.     }
  12. }
* This source code was highlighted with Source Code Highlighter.
  1. public class EnumerationKeyProvider<E extends Enum<E>> implements ProvidesKey<E> {
  2.  
  3.     @Override
  4.     public Object getKey(E item) {
  5.         return item == null ? null : item.name() ;
  6.     }
  7. }
* This source code was highlighted with Source Code Highlighter.
     Теперь когда у нас есть enumeration список, создадим для него контейнер согласно Editor контракту.
  1. public class TaskEditor extends Composite implements Editor<TaskProxy> {
  2.     
  3.     @UiField(provided = true)
  4.     EnumerationListBox<Status> priority = new EnumerationListBox<Status>(Status.class);
  5.     
  6.     public TaskEditor() {
  7.         initWidget(priority);
  8.         
  9.         priority.addValueChangeHandler(new ValueChangeHandler<Status>() {
  10.             @Override
  11.             public void onValueChange(ValueChangeEvent<Status> event) {
  12.                 // and you can do whatever you want with selected event.getValue()
  13.             }
  14.         });
  15.     }
  16. }
* This source code was highlighted with Source Code Highlighter.
     Добавим сюда механизм RequestFactory, который позволяет реализовать уровень доступа к данным на клиенте и сервере. Это позволяет структурировать серверный код в data-ориентированном виде и обеспечивает более высокий уровень абстракции чем GWT-RPC. Первоначально он был создан для CRUD операций на сущности, но позже добавили возможность использования как универсальный механизм RPC.
     Создадим интерфейс TaskProxy для сущности Task и определим необходимые get/set методы. Все методы отображаются(mapped) по именованному соглашению, т.е. имена должны быть идентичными.
  1. @ProxyFor(value = Task.class)
  2. public interface TaskProxy extends EntityProxy {
  3.     
  4.     Status getPriority();
  5.     public void setPriority(Status priority);
  6. }
* This source code was highlighted with Source Code Highlighter.
  1. public class Task {
  2.     @NotNull private Status priority;
  3.     
  4.     public Status getPriority() {
  5.         return priority;
  6.     }
  7.     
  8.     public void setPriority(Status priority) {
  9.         this.priority = priority;
  10.     }
  11. }
* This source code was highlighted with Source Code Highlighter.
     Создание полного client/server-примера, где будут разные Entity, DAO, Proxy, Locator, RequestFactory, RequestContext, Manager-class это уже дело отдельной статьи. А на этом все.

Комментариев нет:

Отправить комментарий