CollectionContainer

Интерфейс CollectionContainer предназначен для работы с коллекцией экземпляров сущности. Это потомок интерфейса InstanceContainer.

CollectionContainer можно определить в XML-дескрипторе следующим образом:

<collection id="departmentsDc"
            class="com.company.onboarding.entity.Department">
    <fetchPlan extends="_base">
        <property name="hrManager" fetchPlan="_base"/>
    </fetchPlan>
        <loader id="departmentsDl" readOnly="true">
        <query>
            <![CDATA[select e from Department e]]>
        </query>
    </loader>
</collection>

Методы

В CollectionContainer определены следующие методы:

  • setItems() - устанавливает коллекцию экземпляров сущности для контейнера.

  • getItems() - возвращает неизменяемый список сущностей, хранимых в контейнере. Используйте этот метод для обхода коллекции, получения потока (Java stream) или экземпляра сущности по его позиции в списке. Если требуется получить экземпляр сущности по его идентификатору, используйте метод getItem(entityId). Например:

    @ViewComponent
    private CollectionContainer<Department> departmentsDc;
    
    private Optional<Department> findByName(String name) {
        return departmentsDc.getItems().stream()
                .filter(department -> Objects.equals(department.getName(), name))
                .findFirst();
    }
  • getMutableItems() - возвращает изменяемый список сущностей, хранимых в контейнере. Все изменения списка, вызванные методами add(), addAll(), remove(), removeAll(), set(), clear(), публикуют событие CollectionChangeEvent. Визуальные компоненты, подписанные на это событие, будут обновлены автоматически. Например:

    @ViewComponent
    private CollectionContainer<Department> departmentsDc;
    
    private void createDepartment() {
        Department department = metadata.create(Department.class);
        department.setName("Operations");
        departmentsDc.getMutableItems().add(department);
    }
    Используйте метод getMutableItems() только тогда, когда необходимо изменить коллекцию. В остальных случаях предпочтительнее использовать getItems().
  • setItem() - устанавливает текущий экземпляр сущности для контейнера. Если передан не null, переданный экземпляр должен уже иметься в коллекции, чтобы быть выбранным. Метод публикует событие ItemChangeEvent.

    Нужно учитывать, что визуальные компоненты, такие как DataGrid, не отслеживают событие ItemChangeEvent, публикуемое контейнером. Поэтому, если вам нужно выбрать строку в DataGrid, используйте selection model компонента DataGrid вместо метода setItem() контейнера, содержащего коллекцию. Текущий экземпляр контейнера также будет изменен, так как контейнер отслеживает события компонента. Пример:

    @ViewComponent
    private DataGrid<Department> departmentsTable;
    
    @ViewComponent
    private CollectionContainer<Department> departmentsDc;
    
    private void selectFirstRow() {
        departmentsTable.getSelectionModel()
                .select(departmentsDc.getItems().get(0));
    }
  • getItem() - переопределяет аналогичный метод интерфейса InstanceContainer и возвращает текущий экземпляр. Если текущий экземпляр не задан, метод выбрасывает исключение. Используйте этот метод, если вы уверены, что для контейнера задан текущий экземпляр, и не хотите дополнительно проверять возвращаемое значение на null.

  • getItemOrNull() - переопределяет аналогичный метод интерфейса InstanceContainer и возвращает текущий экземпляр. Если текущий экземпляр не задан, метод возвращает null. Всегда проверяйте полученное значение на null перед использованием.

  • getItemIndex(entityId) - возвращает позицию экземпляра с данным идентификатором в списке, возвращаемом методами getItems() и getMutableItems(). Этот метод принимает Object, поэтому можно передать как идентификатор, так и сам экземпляр сущности. Реализация контейнера поддерживает отображение идентификаторов на индексы, поэтому метод работает быстро даже с большими списками.

  • getItem(entityId) - возвращает экземпляр из коллекции по его идентификатору. Это сокращенный метод, который сначала получает позицию экземпляра с помощью getItemIndex(entityId), а затем возвращает его из списка через getItems().get(index). Метод выбрасывает исключение, если экземпляр с переданным идентификатором отсутствует в коллекции.

  • getItemOrNull(entityId) - то же, что и getItem(entityId), но возвращает null, если экземпляр с данным идентификатором отсутствует в коллекции. Всегда проверяйте полученное значение на null перед использованием.

  • containsItem(entityId) - возвращает true, если экземпляр с данным идентификатором присутствует в коллекции. Это сокращенный метод, который использует getItemIndex(entityId).

  • replaceItem(entity) - если экземпляр с тем же идентификатором уже есть в контейнере, он заменяется переданным экземпляром. Если такого экземпляра нет, переданный экземпляр добавляется в список. Метод публикует событие CollectionChangeEvent типа SET_ITEM или ADD_ITEMS в зависимости от выполненной операции.

  • setSorter() - задает сортировщик для контейнера. По умолчанию фреймворк создает сортировщик через CollectionContainerSortManager. Менеджер сначала проверяет зарегистрированные бины CollectionContainerSortProvider, а затем использует SorterFactory, который создает стандартный CollectionContainerSorter. При необходимости можно предоставить собственную реализацию.

  • getSorter() - возвращает сортировщик, установленный для данного контейнера.

События

В дополнение к событиям InstanceContainer, интерфейс CollectionContainer позволяет зарегистрировать слушатели для события CollectionChangeEvent, которое вызывается при изменении коллекции сущностей, то есть при добавлении, удалении или замене элементов коллекции. Пример подписки на событие для контейнера, объявленного в XML с идентификатором departmentsDc:

@Subscribe(id = "departmentsDc", target = Target.DATA_CONTAINER)
public void onDepartmentsDcCollectionChange(
        final CollectionContainer.CollectionChangeEvent<Department> event) {
    CollectionChangeType changeType = event.getChangeType(); (1)
    Collection<? extends Department> changes = event.getChanges(); (2)
    // ...
}
1 Возвращает тип изменения: REFRESH, ADD_ITEMS, REMOVE_ITEMS, SET_ITEM.
2 Коллекция сущностей, которые были добавлены в контейнер или удалены из него. Если тип изменения равен REFRESH, фреймворк не может определить, какие именно элементы были добавлены или удалены, поэтому эта коллекция будет пустой.