CollectionContainer

The CollectionContainer interface is designed to hold a collection of entities of the same type. It is a descendant of the InstanceContainer interface.

You can define CollectionContainer in the XML descriptor in the following way:

<data readOnly="true">
    <collection id="customersDc"
                class="ui.ex1.entity.Customer">
        <fetchPlan extends="_base"/>
        <loader id="customersDl" >
            <query>
                <![CDATA[select e from uiex1_Customer e]]>
            </query>
        </loader>
    </collection>
</data>

Methods

CollectionContainer defines the following specific methods:

  • setItems() - sets a collection of entities to the container.

  • getItems() - returns an immutable list of entities stored in the container. Use this method to iterate over the collection, to get a stream or to get an instance by its position in the list. If you need to get an entity instance by its id, use getItem(entityId). For example:

    @Autowired
    private CollectionContainer<Customer> customersDc;
    
    private Optional<Customer> findByName(String name) {
        return customersDc.getItems().stream()
                .filter(customer -> Objects.equals(customer.getLastName(), name))
                .findFirst();
    }
  • getMutableItems() - returns a mutable list of entities stored in the container. All list changes caused by the add(), addAll(), remove(), removeAll(), set(), clear() methods produce CollectionChangeEvent, so subscribed visual components will update accordingly. For example:

    @Autowired
    private CollectionContainer<Customer> customersDc;
    
    private void createCustomer() {
        Customer customer = metadata.create(Customer.class);
        customer.setFirstName("John");
        customer.setLastName("Doe");
        customersDc.getMutableItems().add(customer);
    }
    Use getMutableItems() only when you want to change the collection. In other cases, it is preferable to use getItems().
  • setItem() - sets the current item for this container. If the provided item is not null, it must exist in the collection. The method sends ItemChangeEvent.

    Please note that visual components like Table do not listen to ItemChangeEvent sent by the container. So if you want to select a row in a table, use the setSelected() method of the table instead of the setItem() method of the collection container. The current item of the container will also be changed because the container listens to the component. For example:

    @Autowired
    private CollectionContainer<Customer> customersDc;
    
    @Autowired
    private GroupTable<Customer> customersTable;
    
    private void selectFirstRow() {
        customersTable.setSelected(customersDc.getItems().get(0));
    }
  • getItem() - overrides the method of InstanceContainer and returns the current item. If the current item is not set, the method throws an exception. Use this method when you are sure that the current item has been set for the container, then you don’t have to check the returned value for null.

  • getItemOrNull() - overrides the method of InstanceContainer and returns the current item. If the current item is not set, this method returns null. Please always check the returned value for null before using it.

  • getItemIndex(entityId) - returns the position of an instance with the given id in the list returned by the getItems() and getMutableItems() methods. This method accepts Object and you can pass either id or the entity instance itself. The container implementation maintains a map of ids to indexes, so the method works fast even on large lists.

  • getItem(entityId) - returns an instance from the collection by its id. It’s a shortcut method that first obtains the instance position using getItemIndex(entityId) and then returns the instance from the list using getItems().get(index). The method throws an exception if the instance with the specified id doesn’t exist in the collection.

  • getItemOrNull(entityId) - same as getItem(entityId) but returns null if the instance with the specified id doesn’t exist in the collection. Please always check the returned value for null before using it.

  • containsItem(entityId) - returns true if an instance with the specified id exists in the collection. It’s a shortcut method that uses getItemIndex(entityId) under the hood.

  • replaceItem(entity) - if the item with the same id exists in the container, it is replaced with the given instance. If not, the given instance is added to the items list. The method sends CollectionChangeEvent of the SET_ITEM or ADD_ITEMS type depending on what has been done.

  • setSorter() - sets the given sorter for this container. A standard implementation of the Sorter interface is CollectionContainerSorter. It is set by the framework automatically when the container is associated with a loader. You can provide your own implementation if needed.

  • getSorter() - returns the sorter currently set for this container.

Events

In addition to events of InstanceContainer, the CollectionContainer interface allows you to register listeners to the CollectionChangeEvent event which is sent when the container items collection is changed: on adding, removing and replacing elements. Example of subscribing to the event for a container defined in the screen XML with customersDc id:

@Subscribe(id = "customersDc", target = Target.DATA_CONTAINER)
public void onCustomersDcCollectionChange(CollectionContainer.CollectionChangeEvent<Customer> event) {
    CollectionChangeType changeType = event.getChangeType(); (1)
    Collection<? extends Customer> changes = event.getChanges(); (2)
    // ...
}
1 Gets a type of changes: REFRESH, ADD_ITEMS, REMOVE_ITEMS, SET_ITEM.
2 Collection of entities that were added or removed from the container. If the change type is REFRESH, the framework cannot determine what exactly items were added or removed, so this collection is empty.