public abstract class ListEvent<E> extends EventObject
EventList
. A ListEventListener
can
be registered on an EventList
to observe and handle these ListEvents.
A simple change is characterized by its type and the corresponding list index. The type
indicates the INSERT
, UPDATE
or DELETE
operation that took place at
the specified index.
Here are some examples:
eventList.add(0, value)
produces an INSERT
at index 0 ("I0")eventList.add(value)
on a list with size 5 produces an INSERT
at index 5
("I5")eventList.remove(3)
on a list with appropriate size produces a DELETE
at
index 3 ("D3")eventList.remove(value)
on a list which contains the value at index 2 produces a
DELETE
at index 2 ("D2")eventList.clear()
on a list with size 1 produces a DELETE
at index 0
("D0")eventList.set(1, value)
on a list with appropriate size produces an UPDATE
at index 1 ("U1")A ListEvent is capable of representing a sequence of such changes. Consider this example:
EventList<String> list = GlazedLists.eventListOf("A", "D", "E"); list.addAll(1, GlazedLists.eventListOf("B", "C"));This operation inserts element "B" at index 1 ("I1") and element "C" at index 2 ("I2"). These two changes are not represented as two separate ListEvents but as a sequence of changes ("I1", "I2") within one ListEvent. Because of this, the ListEvent is accessed like an iterator with the user iterating over the contained sequence of changes, see below. Here is another example:
EventList<String> list = GlazedLists.eventListOf("A", "B", "C", "B"); list.removeAll(GlazedLists.eventListOf("A", "C"));This will remove element "A" at index 0 and element "C" at original index 2. But the corresponding ListEvent looks like ("D0","D1"). The list index of the second deletion is automatically adjusted, taking the first deletion into account.
Note, that the sequence of changes is ordered by ascending list indexes.
The typical pattern to iterate over a ListEvent is:
ListEvent listChanges = ... while (listChanges.next()) { final int type = listChanges.getType()); final int index = listChanges.getIndex(); // handle insert, update or delete at index ... }If you need to iterate over a ListEvent again, that's of course possible, just
reset
the ListEvent and iterate again.
In addition to simple changes, ListEvent supports the view on list changes as blocks. This basically means, that simple changes of one particular type that build a continuous range of indexes are grouped together. Consider this example:
EventList<String> list = GlazedLists.eventListOf("A", "A", "B", "B", "C", "C"); list.removeAll(GlazedLists.eventListOf("A", "C"));This deletes all occurences of elements "A" and "C" from the list. So there is a deletion from index 0 to index 1 (inclusive) and another deletion from index 2 to 3. So, instead of modeling each change one by one like ("D0", "D0", "D2", "D2"), you can view the changes in blocks "D0-1" and "D2-3". This view is exactly what ListEvent offers by iterating the changes in blocks:
ListEvent listChanges = ... while (listChanges.nextBlock()) { final int type = listChanges.getType()); final int startIndex = listChanges.getBlockStartIndex(); final int endIndex = listChanges.getBlockEndIndex(); // handle insert, update or delete from startIndex to endIndex ... }In the above example you would have two blocks of changes of type
DELETE
instead of four
simple changes.
It is up to you, which iteration style you choose. Handling blocks of changes might yield a
better performance.
While it is possible to change the style during one iteration, it is not recommended, because you have to be careful to not miss some changes. Refering to the last example above, the following code would skip the change "D1":
ListEvent listChanges = ...// ("D0", "D0", "D2", "D2") vs. ("D0-1", "D2-3") if (listChanges.next()) { final int type = listChanges.getType(); final int index = listChanges.getIndex(); // handle delete at index 0 // ... while (listChanges.nextBlock()) {// move to next block starting at index 2, skipping change at index 1, which is part of the first block ! final int type2 = listChanges.getType(); final int startIndex = listChanges.getBlockStartIndex(); final int endIndex = listChanges.getBlockEndIndex(); // handle deletion from startIndex 2 to endIndex 3 ... } }This kind of code is unusual, error-prone and should be avoided.
There is a special kind of change, a reordering
ListEvent. It indicates a
reordering of the list elements, for example triggered by setting a new comparator on a
SortedList
.
A reorder event cannot contain other regular changes in the current implementation. Instead it
provides a reorder map
, which maps the new indexes of the list elements
to the old indexes. For details of the mapping see the javadoc of method
getReorderMap()
.
ListEventListener
s, that don't explicitly check for a reorder event, will observe a
deletion of all list elements with a subsequent re-insertion instead.
In the future, ListEvent will provide even more information about the list changes to be more self-contained:
getOldValue()
getNewValue()
getOldValue()
and
getNewValue()
Note, that providing the old and new elements has an impact on the granularity of blocks of changes. For example, consider the clear operation on a list:
EventList<String> list = GlazedLists.eventListOf("A", "B", "C"); list.clear();Without considering the old and new elements, the ListEvent would consist of one block: a deletion from index 0 to 2 ("D0-2"). With the feature of providing the deleted elements, the ListEvent cannot consist of one block anymore, because of the additional requirement, that the old element must have the same value in one block:
ListEvent listChanges = ... while (listChanges.nextBlock()) { final int type = listChanges.getType()); final int startIndex = listChanges.getBlockStartIndex(); final int endIndex = listChanges.getBlockEndIndex(); final Object oldValue = listChanges.getOldValue(); final Object newValue = listChanges.getNewValue(); // handle insert, update or delete from startIndex to endIndex ... }So, a sequence of simple changes can only be grouped as block, when the type, as well as the old and new value are equal.
Modifier and Type | Field and Description |
---|---|
static int |
DELETE
different types of changes
|
static int |
INSERT |
protected EventList<E> |
sourceList
the list that has changed
|
static Object |
UNKNOWN_VALUE
indicates a removed element whose value is unknown
|
static int |
UPDATE |
source
Modifier | Constructor and Description |
---|---|
protected |
ListEvent(EventList<E> sourceList)
Create a new list change sequence that uses the source master list for the source of changes.
|
Modifier and Type | Method and Description |
---|---|
abstract ListEvent<E> |
copy()
Create a bitwise copy of this
ListEvent . |
abstract int |
getBlockEndIndex()
Gets the last row of the current block of changes.
|
abstract int |
getBlocksRemaining()
Deprecated.
this method depends on a particular implementation of how list events are stored
internally, and this implementation has since changed.
|
abstract int |
getBlockStartIndex()
Gets the first row of the current block of changes.
|
abstract int |
getIndex()
Gets the current row index.
|
abstract E |
getNewValue()
Deprecated.
this is a developer preview API that is not yet fit for human
consumption. Hopefully the full implementation is complete for Glazed Lists 2.0.
|
abstract E |
getOldValue()
Deprecated.
this is a developer preview API that is not yet fit for human
consumption. Hopefully the full implementation is complete for Glazed Lists 2.0.
|
abstract int[] |
getReorderMap()
Gets the reorder map of this list.
|
EventList<E> |
getSourceList()
Gets the List where this event originally occured.
|
abstract int |
getType()
Gets the type of the current change, which should be one of ListEvent.INSERT, UPDATE, or
DELETE.
|
abstract boolean |
hasNext()
Without incrementing the implicit iterator, this tests if there is another change to view.
|
abstract boolean |
isReordering()
Tests if this change is a complete reordering of the list.
|
abstract boolean |
next()
Increments the change sequence to view the next change.
|
abstract boolean |
nextBlock()
Increments the change sequence to view the next change block.
|
abstract void |
reset()
Resets this event's position to the previously-marked position.
|
abstract String |
toString()
Gets this event as a String.
|
static <E> E |
unknownValue()
Returns a value indicating a removed element whose value is unknown.
|
getSource
public static final int DELETE
public static final int UPDATE
public static final int INSERT
public static final Object UNKNOWN_VALUE
public static final <E> E unknownValue()
public abstract void reset()
TransformedList
s that require multiple-passes of the ListEvent
in order to
process it.public abstract boolean next()
public abstract boolean hasNext()
public abstract boolean nextBlock()
public abstract boolean isReordering()
If it's a reordering, you can determine the changed element positions with the help of the reorder map.
getReorderMap()
public abstract int[] getReorderMap()
isReordering()
returns true
.
The size of the returned array is equal to the list size. The array value at index i is the previous index (before the reordering) of the list element at index i (after the reordering).
list before the reordering: "A", "B", "C"
list after the reordering: "C", "B", "A"
The reorder map of the corresponding ListEvent would look like: map[0]=2; map[1]=1; map[2]=0
IllegalStateException
- if this is not a reordering eventisReordering()
public abstract int getIndex()
public abstract int getBlockStartIndex()
public abstract int getBlockEndIndex()
public abstract int getType()
@Deprecated public abstract E getOldValue()
UNKNOWN_VALUE
.@Deprecated public abstract E getNewValue()
UNKNOWN_VALUE
.@Deprecated public abstract int getBlocksRemaining()
public EventList<E> getSourceList()
public abstract String toString()
toString
in class EventObject
Copyright © 2024 levigo holding gmbh. All rights reserved.