4.5.1.3.6. Компаньоны контроллеров

Базовые классы контроллеров расположены в модуле gui базового проекта cuba и не содержат ссылок на классы реализации визуальных компонентов (Swing или Vaadin), что дает возможность использовать их в клиентах обоих типов. Вместо этого базовые классы контроллеров реализуют дополнительный интерфейс Window.Wrapper и делегируют выполнение "обернутому" окну.

В то же время конкретные классы контроллеров могут быть расположены как в модуле gui, так и в web или desktop, в зависимости от применяемых в проекте клиентских блоков и специфики экрана. Если контроллер является универсальным, но для разных типов клиента требуется дополнительная функциональность, ее можно определить в так называемых классах-компаньонах.

Класс-компаньон располагается в модуле клиента соответствующего типа (web или desktop) и реализует интерфейс, задаваемый в использующем его контроллере. Класс компаньона задается в элементе companions XML-дескриптора экрана. Контроллер может получить ссылку на экземпляр компаньона с помощью инжекции или вызовом getCompanion(), и в нужный момент передать ему управление, например, для дополнительной инициализации визуальных компонентов специфичным для данного типа клиента способом.

Например, необходимо раздельно для веб и десктоп клиентов проинициализировать таблицу некоторого экрана. Тогда в контроллере экрана, расположенном в модуле gui, определяем интерфейс компаньона и делегируем ему инициализацию таблицы:

public class CustomerBrowse extends AbstractLookup {

  public interface Companion {
      void initTable(Table table);
  }

  @Inject
  protected Table table;

  @Inject
  protected Companion companion;

  @Override
  public void init(Map<String, Object> params) {
      if (companion != null) {
          companion.initTable(table);
      }
  }
}

В модулях web и desktop создаем соответствующие классы реализации компаньона:

public class WebCustomerBrowseCompanion implements CustomerBrowse.Companion {
  @Override
  public void initTable(Table table) {
      com.vaadin.ui.Table webTable = (com.vaadin.ui.Table) WebComponentsHelper.unwrap(table);
      // do something specific to Vaadin table
  }
}
public class DesktopCustomerBrowseCompanion implements CustomerBrowse.Companion {
  @Override
  public void initTable(Table table) {
      javax.swing.JTable desktopTable = (javax.swing.JTable) DesktopComponentsHelper.unwrap(table);
      // do something specific to Swing table
  }
}

И регистрируем классы реализации компаньона в XML-дескрипторе экрана:

<window ...
      class="com.company.sample.gui.customers.CustomerBrowse">
  <companions>
      <web class="com.company.sample.web.customers.WebCustomerBrowseCompanion"/>
      <desktop class="com.company.sample.desktop.customers.DesktopCustomerBrowseCompanion"/>
  </companions>
  <dsContext>...</dsContext>
  <layout>...</layout>
</window>

Так как классы-компаньоны расположены в web и desktop модулях, в них можно использовать метод unwrap() классов WebComponentsHelper и DesktopComponentsHelper для извлечения из интерфейса Table ссылок на реализующие таблицу Vaadin и Swing компоненты, и работать с ними непосредственно.