This tutorial contains notes about GlazedLists.

1. What is GlazedLists?

GlazedLists is an open source project, which is hosted on GitHub (https://github.com/glazedlists/glazedlists). It is distributed under the LGPL and MPL license.

Basically it provides list implementations, which propagate events to it’s listeners once a list is changed. It also provides the possibility to transform the list, without having an impact on the original list.

Therefore it is mainly used as underlying data model for list UI widgets, like tables and trees.

It provides extensions for the UI toolkits Swing and SWT out of the box.

Also Nebula NatTable provides extensions for GlazedLists and makes use of their list implementation.

2. EventList

2.1. EventList overview

The EventList interface simply extends java.util.List and therefore can be used like every other Java list implementation.

package ca.odell.glazedlists;

import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;
import ca.odell.glazedlists.event.ListEventPublisher;
import ca.odell.glazedlists.util.concurrent.ReadWriteLock;

import java.util.Collection;
import java.util.List;

public interface EventList<E> extends List<E> {

    public void addListEventListener(ListEventListener<? super E> listChangeListener);

    public void removeListEventListener(ListEventListener<? super E> listChangeListener);

    public ReadWriteLock getReadWriteLock();

    public ListEventPublisher getPublisher();

    public void dispose();
}

It allows to attach listeners to the List once the list is changed. Also the ListEventPublisher can be obtained, which propagates the changes.

For concurrency it provides a getReadWriteLock() and a dispose() method to ensure that the list can be garbage collected, e.g., when the list itself is attached as a listener.

2.2. Creating an EventList

The easiest way to create an EventList is to use the BasicEventList.

EventList<Object> basicEventList = new BasicEventList<>();

If a Collection instance is already created or obtained from somewhere else a convenience method on the GlazedLists class can be used:

List<String> listOfNames = getListOfNames();
EventList<String> eventList = GlazedLists.eventList(listOfNames);

3. Decorating EventLists to extend the functionality

In GlazedLists the decorator design pattern is used a lot in order to add functionality to a given EventList.

3.1. Concurrency

Even though the EventList class provides a getter for ReadWriteLock it is not thread safe by default.

List<String> listOfNames = getListOfNames();
EventList<String> eventList = GlazedLists.eventList(listOfNames);
EventList<String> threadSafeEventList = GlazedLists.threadSafeList(eventList);

3.2. Sorting an EventList

To automatically sort an EventList it can be decorated into a SortedList.

EventList<? extends Comparable> basicEventList = new BasicEventList<>();
SortedList<? extends Comparable> sortedList = new SortedList<>(basicEventList);
List<String> listOfNames = getListOfNames();
EventList<String> eventList = GlazedLists.eventList(listOfNames);
// the second parameter is a java.util.Comparator<T>
SortedList<String> sortedList = new SortedList<>(eventList, (s, s2) -> s.compareTo(s2));

You can also pass null as java.util.Comparator<T> and apply it later.

new SortedList<>(eventList, null);

3.3. Observing the properties of objects in an EventList

The EventList is able to fire events upon a change to the list itself. So adding, removing and setting elements for the list instance can be tracked by using a plain EventList, but if also the properties of elements in the list should be tracked an ObservableElementList will be the right choice.

The ObservableElementList takes an EventList and a ObservableElementList.Connector as parameters. By implementing the Connector interface a possibility to track the elements in the list can be provided.
It has 3 methods:

public interface Connector<E> {
    public EventListener installListener(E element);

    public void uninstallListener(E element, EventListener listener);

    public void setObservableElementList(ObservableElementList<? extends E> list);
}

The GlazedLists class provides some methods to create default Connector instances like GlazedLists.beanConnector(Person.class) or GlazedLists.observableConnector().

An ObservableElementList for Person objects could be created like this:

EventList<Person> personEventList = GlazedLists.eventList(persons);
ObservableElementList<Person> observableElementList =
    new ObservableElementList<>(personEventList, GlazedLists.beanConnector(Person.class));

4. GlazedLists resources