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

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

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

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

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

public class CustomerBrowse extends AbstractLookup {

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

    @Inject
    protected Table<Customer> 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<Customer> 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<Customer> 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 компоненты, и работать с ними непосредственно.