Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## com.jgoodies.binding.list
Class IndirectListModel<E>

    java.lang.Object
      com.jgoodies.common.bean.AbstractBean
          com.jgoodies.binding.beans.Model
              com.jgoodies.binding.list.IndirectListModel<E>

Type Parameters:
  `E` - the type of the list elements

All Implemented Interfaces:
  com.jgoodies.common.bean.ObservableBean, com.jgoodies.common.bean.ObservableBean2, Serializable, ListModel

Direct Known Subclasses:
  SelectionInList

    public class IndirectListModel<E>

extends Model
implements ListModel

A ListModel implementation that holds a List or ListModel in a ValueModel. If you hold a List, this class can only report that the List has been replaced; this is done by firing a PropertyChangeEvent for the list property. Also, a `ListDataEvent` is fired that reports a complete change. In contrast, if you use a ListModel it will report the same PropertyChangeEvent. But fine grained changes in the ListModel will be fired by this class to notify observes about changes in the content, added and removed elements.

If the list content doesn't change at all, or if it always changes completely, you can work well with both List content and ListModel content. But if the list structure or content changes, the ListModel reports more fine grained events to registered ListDataListeners, which in turn allows list views to chooser better user interface gestures: for example, a table with scroll pane may retain the current selection and scroll offset.

If you want to combine List operations and the ListModel change reports, you may consider using an implementation that combines these two interfaces, for example `com.jgoodies.common.collect.ArrayListModel` or `com.jgoodies.common.collect.LinkedListModel`.

Important Note: If you change the ListModel instance, either by calling `#setListModel(ListModel)` or by setting a new value to the underlying list holder, you must ensure that the list holder throws a PropertyChangeEvent whenever the instance changes. This event is used to remove a ListDataListener from the old ListModel instance and is later used to add it to the new ListModel instance. It is easy to violate this constraint, just because Java's standard PropertyChangeSupport helper class that is used by many beans, checks a changed property value via `#equals`, not `==`. For example, if you change the IndirectListModel's list model from an empty list `L1` to another empty list instance `L2`, the PropertyChangeSupport won't generate a PropertyChangeEvent, and so, the IndirectListModel won't know about the change, which may lead to unexpected behavior.

This binding library provides some help for firing PropertyChangeEvents if the old ListModel and new ListModel are equal but not the same. Class `ExtendedPropertyChangeSupport` allows to permanently or individually check the identity (using `==`) instead of checking the equity (using `#equals`). Class `Model` uses this extended property change support. And class `ValueHolder` uses it too and can be configured to always test the identity.

This class provides public convenience methods for firing ListDataEvents, see the methods `#fireContentsChanged`, `#fireIntervalAdded`, and `#fireIntervalRemoved`. These are automatically invoked if the list holder holds a ListModel that fires these events. If on the other hand the underlying List or ListModel does not fire a required ListDataEvent, you can use these methods to notify presentations about a change. It is recommended to avoid sending duplicate ListDataEvents; hence check if the underlying ListModel fires the necessary events or not.

Constraints: The list holder holds instances of `List` or `ListModel`. If the ListModel changes, the underlying ValueModel must fire a PropertyChangeEvent.

Since:
  2.0
Version:
  $Revision: 1.13 $
Author:
  Karsten Lentzsch
See Also:
  `List`, `ListModel`, `SelectionInList`, `ValueModel`, `ComboBoxAdapter`, `AbstractTableAdapter`, `ExtendedPropertyChangeSupport`, `Model`, `ValueHolder`, Serialized Form

Field Summary
`static String` | `PROPERTYNAME_LIST` The name of the bound write-only list property.
`static String` | `PROPERTYNAME_LIST_HOLDER` The name of the bound read-write listHolder property.

Fields inherited from class com.jgoodies.common.bean.AbstractBean
`changeSupport`

Constructor Summary
`IndirectListModel()` Constructs an IndirectListModel with an empty initial `ArrayListModel`.
`IndirectListModel(E[] listItems)` Constructs an IndirectListModel on the given item array.
`IndirectListModel(List<E> list)` Constructs an IndirectListModel on the given list.
`IndirectListModel(ListModel listModel)` Constructs an IndirectListModel on the given list model using a default list holder.
`IndirectListModel(ValueModel listHolder)` Constructs an IndirectListModel on the given list holder.

Method Summary
`void` | `addListDataListener(ListDataListener l)` Adds a listener to the list that's notified each time a change to the data model occurs.
`protected ListDataListener` | `createListDataChangeHandler()` Creates and returns the ListDataListener used to observe changes in the underlying ListModel.
`void` | `fireContentsChanged(int index0, int index1)` Notifies all registered ListDataListeners that the contents of one or more list elements has changed.
`void` | `fireIntervalAdded(int index0, int index1)` Notifies all registered ListDataListeners that one or more elements have been added to this IndirectListModel's List/ListModel.
`void` | `fireIntervalRemoved(int index0, int index1)` Notifies all registered ListDataListeners that one or more elements have been removed from this IndirectListModel's List/ListModel.
`protected void` | `fireListChanged(int oldLastIndex, int newLastIndex)` Notifies all registered ListDataListeners that this ListModel has changed from an old list to a new list content.
`E` | `getElementAt(int index)` Returns the value at the specified index, `null` if the list model is `null`.
`List<E>` | `getList()` Returns the list holder's List or an empty List, if it holds `null`.
`ListDataListener[]` | `getListDataListeners()` Returns an array of all the list data listeners registered on this `IndirectListModel`.
`ValueModel` | `getListHolder()` Returns the model that holds the List/ListModel.
`ListModel` | `getListModel()` Returns the list holder's ListModel or an empty ListModel, if it holds `null`.
`int` | `getSize()` Returns the length of the list, `0` if the list model is `null`.
`protected static int` | `getSize(Object aListListModelOrNull)` Returns the length of the given list, `0` if the list model is `null`.
`boolean` | `isEmpty()` Checks and answers if the list is empty or `null`.
`void` | `release()` Removes the internal listeners from the list holder.
`void` | `removeListDataListener(ListDataListener l)` Removes a listener from the list that's notified each time a change to the data model occurs.
`void` | `setList(List<E> newList)` Sets the given list as value of the list holder.
`void` | `setListHolder(ValueModel newListHolder)` Sets a new list holder.
`void` | `setListModel(ListModel newListModel)` Sets the given list model as value of the list holder.
`protected void` | `updateList(Object oldList, int oldSize, Object newList)` Removes the list data change handler from the old list in case it is a `ListModel` and adds it to new one in case it is a `ListModel`.

Methods inherited from class com.jgoodies.binding.beans.Model
`createPropertyChangeSupport, firePropertyChange`

Methods inherited from class com.jgoodies.common.bean.AbstractBean
`addPropertyChangeListener, addPropertyChangeListener, addVetoableChangeListener, addVetoableChangeListener, fireIndexedPropertyChange, fireIndexedPropertyChange, fireIndexedPropertyChange, fireMultiplePropertiesChanged, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, fireVetoableChange, getPropertyChangeListeners, getPropertyChangeListeners, getVetoableChangeListeners, getVetoableChangeListeners, removePropertyChangeListener, removePropertyChangeListener, removeVetoableChangeListener, removeVetoableChangeListener`

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

Field Detail

### PROPERTYNAME_LIST

    public static final String PROPERTYNAME_LIST

  The name of the bound write-only list property.

  See Also:
    Constant Field Values

### PROPERTYNAME_LIST_HOLDER

    public static final String PROPERTYNAME_LIST_HOLDER

  The name of the bound read-write listHolder property.

  See Also:
    Constant Field Values

Constructor Detail

### IndirectListModel

    public IndirectListModel()

  Constructs an IndirectListModel with an empty initial `ArrayListModel`.

### IndirectListModel

    public IndirectListModel(E[] listItems)

  Constructs an IndirectListModel on the given item array. The specified array will be converted to a List.

  Changes to the list "write through" to the array, and changes to the array contents will be reflected in the list.

  Parameters:
    `listItems` - the array of initial items
  Throws:
    `NullPointerException` - if `listItems` is `null`

### IndirectListModel

    public IndirectListModel(List<E> list)

  Constructs an IndirectListModel on the given list.

  Note: Favor `ListModel` over `List` when working with an IndirectListModel. Why? The IndirectListModel can work with both types. What's the difference? ListModel provides all list access features required by the IndirectListModel's. In addition it reports more fine grained change events, instances of `ListDataEvents`. In contrast developer often create Lists and operate on them and the ListModel may be inconvenient for these operations.

  A convenient solution for this situation is to use the `ArrayListModel` and `LinkedListModel` classes. These implement both List and ListModel, offer the standard List operations and report the fine grained ListDataEvents.

  Parameters:
    `list` - the initial list

### IndirectListModel

    public IndirectListModel(ListModel listModel)

  Constructs an IndirectListModel on the given list model using a default list holder.

  Parameters:
    `listModel` - the initial list model

### IndirectListModel

    public IndirectListModel(ValueModel listHolder)

  Constructs an IndirectListModel on the given list holder.

  Constraints: 1) The listHolder must hold instances of List or ListModel and 2) must report a value change whenever the value's identity changes. Note that many bean properties don't fire a PropertyChangeEvent if the old and new value are equal - and so would break this constraint. If you provide a ValueHolder, enable its identityCheck feature during construction. If you provide an adapted bean property from a bean that extends the JGoodies `Model` class, you can enable the identity check feature in the methods `#firePropertyChange` by setting the trailing boolean parameter to `true`.

  Parameters:
    `listHolder` - holds the list or list model
  Throws:
    `NullPointerException` - if `listHolder` is `null`

Method Detail

### getList

    public final List<E> getList()

  Returns the list holder's List or an empty List, if it holds `null`. Throws an exception if the list holder holds any other type, including ListModels.

  Returns:
    the List content or an empty List if the content is `null`
  Throws:
    `ClassCastException` - if the list holder is neither `null` nor a List
  Since:
    2.0
  See Also:
    `setList(List)`, `getListModel()`, `setListModel(ListModel)`

### setList

    public final void setList(List<E> newList)

  Sets the given list as value of the list holder.

  Note: Favor `ListModel` over `List` when working with an IndirectListModel. Why? The IndirectListModel can work with both types. What's the difference? ListModel provides all list access features required by the IndirectListModel's. In addition it reports more fine grained change events, instances of `ListDataEvents`. In contrast developer often create Lists and operate on them and the ListModel may be inconvenient for these operations.

  A convenient solution for this situation is to use the `ArrayListModel` and `LinkedListModel` classes. These implement both List and ListModel, offer the standard List operations and report the fine grained ListDataEvents.

  Parameters:
    `newList` - the list to be set as new list content
  See Also:
    `getList()`, `getListModel()`, `setListModel(ListModel)`

### getListModel

    public final ListModel getListModel()

  Returns the list holder's ListModel or an empty ListModel, if it holds `null`. Throws an exception if the list holder holds any other type, including Lists.

  Returns:
    the ListModel content or an empty ListModel if the content is `null`
  Throws:
    `ClassCastException` - if the list holder is neither `null` nor a ListModel
  See Also:
    `setListModel(ListModel)`, `setList(List)`

### setListModel

    public final void setListModel(ListModel newListModel)

  Sets the given list model as value of the list holder.

  Parameters:
    `newListModel` - the list model to be set as new list content
  See Also:
    `getListModel()`, `setList(List)`

### getListHolder

    public final ValueModel getListHolder()

  Returns the model that holds the List/ListModel.

  Returns:
    the model that holds the List/ListModel

### setListHolder

    public final void setListHolder(ValueModel newListHolder)

  Sets a new list holder. Does nothing if old and new holder are equal. Removes the list change handler from the old holder and adds it to the new one. In case the list holder contents is a ListModel, the list data change handler is updated too by invoking `#updateListDataRegistration` in the same way as done in the list change handler.

  TODO: Check and verify whether the list data registration update can be performed in one step after the listHolder has been changed - instead of remove the list data change handler, then changing the listHolder, and finally adding the list data change handler.

  Parameters:
    `newListHolder` - the list holder to be set
  Throws:
    `NullPointerException` - if the new list holder is `null`
    `IllegalArgumentException` - if the listHolder is a ValueHolder that doesn't check the identity when changing its value

### isEmpty

    public final boolean isEmpty()

  Checks and answers if the list is empty or `null`.

  Returns:
    true if the list is empty or `null`, false otherwise

### getSize

    public final int getSize()

  Returns the length of the list, `0` if the list model is `null`.

  Specified by:
    `getSize` in interface `ListModel`
  Returns:
    the size of the list, `0` if the list model is `null`

### getElementAt

    public final E getElementAt(int index)

  Returns the value at the specified index, `null` if the list model is `null`.

  Specified by:
    `getElementAt` in interface `ListModel`
  Parameters:
    `index` - the requested index
  Returns:
    the value at `index`, `null` if the list model is `null`
  Throws:
    `NullPointerException` - if the list holder's content is null

### addListDataListener

    public final void addListDataListener(ListDataListener l)

  Adds a listener to the list that's notified each time a change to the data model occurs.

  Specified by:
    `addListDataListener` in interface `ListModel`
  Parameters:
    `l` - the `ListDataListener` to be added

### removeListDataListener

    public final void removeListDataListener(ListDataListener l)

  Removes a listener from the list that's notified each time a change to the data model occurs.

  Specified by:
    `removeListDataListener` in interface `ListModel`
  Parameters:
    `l` - the `ListDataListener` to be removed

### getListDataListeners

    public final ListDataListener[] getListDataListeners()

  Returns an array of all the list data listeners registered on this `IndirectListModel`.

  Returns:
    all of this model's `ListDataListener`s, or an empty array if no list data listeners are currently registered
  See Also:
    `addListDataListener(ListDataListener)`, `removeListDataListener(ListDataListener)`

### fireContentsChanged

    public final void fireContentsChanged(int index0,
                                          int index1)

  Notifies all registered ListDataListeners that the contents of one or more list elements has changed. The changed elements are specified by the closed interval index0, index1 -- the end points are included. Note that index0 need not be less than or equal to index1.

  If the list holder holds a ListModel, this IndirectListModel listens to ListDataEvents fired by that ListModel, and forwards these events by invoking the associated `#fireXXX` method, which in turn notifies all registered ListDataListeners. Therefore if you fire ListDataEvents in an underlying ListModel, you don't need this method and should not use it to avoid sending duplicate ListDataEvents.

  Parameters:
    `index0` - one end of the new interval
    `index1` - the other end of the new interval
  Since:
    1.0.2
  See Also:
    `ListModel`, `ListDataListener`, `ListDataEvent`

### fireIntervalAdded

    public final void fireIntervalAdded(int index0,
                                        int index1)

  Notifies all registered ListDataListeners that one or more elements have been added to this IndirectListModel's List/ListModel. The new elements are specified by a closed interval index0, index1 -- the end points are included. Note that index0 need not be less than or equal to index1.

  If the list holder holds a ListModel, this IndirectListModel listens to ListDataEvents fired by that ListModel, and forwards these events by invoking the associated `#fireXXX` method, which in turn notifies all registered ListDataListeners. Therefore if you fire ListDataEvents in an underlying ListModel, you don't need this method and should not use it to avoid sending duplicate ListDataEvents.

  Parameters:
    `index0` - one end of the new interval
    `index1` - the other end of the new interval
  Since:
    1.0.2
  See Also:
    `ListModel`, `ListDataListener`, `ListDataEvent`

### fireIntervalRemoved

    public final void fireIntervalRemoved(int index0,
                                          int index1)

  Notifies all registered ListDataListeners that one or more elements have been removed from this IndirectListModel's List/ListModel. `index0` and `index1` are the end points of the interval that's been removed. Note that `index0` need not be less than or equal to `index1`.

  If the list holder holds a ListModel, this IndirectListModel listens to ListDataEvents fired by that ListModel, and forwards these events by invoking the associated `#fireXXX` method, which in turn notifies all registered ListDataListeners. Therefore if you fire ListDataEvents in an underlying ListModel, you don't need this method and should not use it to avoid sending duplicate ListDataEvents.

  Parameters:
    `index0` - one end of the removed interval, including `index0`
    `index1` - the other end of the removed interval, including `index1`
  Since:
    1.0.2
  See Also:
    `ListModel`, `ListDataListener`, `ListDataEvent`

### release

    public void release()

  Removes the internal listeners from the list holder. If the current list is a ListModel, the internal ListDataListener is removed from it. This IndirectListModel must not be used after calling `#release`.

  To avoid memory leaks it is recommended to invoke this method, if the list holder, selection holder, or selection index holder live much longer than this IndirectListModel. Instead of releasing the IndirectListModel, you typically make the list holder obsolete by releasing the PresentationModel or BeanAdapter that has created them before.

  As an alternative you may use ValueModels that in turn use event listener lists implemented using `WeakReference`.

  Basically this release method performs the reverse operation performed during the IndirectListModel construction.

  Since:
    1.2
  See Also:
    `PresentationModel.release()`, `BeanAdapter.release()`, `WeakReference`

### createListDataChangeHandler

    protected ListDataListener createListDataChangeHandler()

  Creates and returns the ListDataListener used to observe changes in the underlying ListModel. It is re-registered in `#updateListModel`.

  Returns:
    the ListDataListener that handles changes in the underlying ListModel

### updateList

    protected void updateList(Object oldList,
                              int oldSize,
                              Object newList)

  Removes the list data change handler from the old list in case it is a `ListModel` and adds it to new one in case it is a `ListModel`. It then fires a property change for the list and a contents change event for the list content.

  Parameters:
    `oldList` - the old list content
    `oldSize` - the size of the old List content
    `newList` - the new list content
  See Also:
    `JTable.tableChanged(javax.swing.event.TableModelEvent)`

### fireListChanged

    protected final void fireListChanged(int oldLastIndex,
                                         int newLastIndex)

  Notifies all registered ListDataListeners that this ListModel has changed from an old list to a new list content. If the old and new list size differ, a remove or add event for the removed or added interval is fired. A content change is reported for the interval common to the old and new list.

  This method is invoked by #updateList during the transition from an old List(Model) to a new List(Model).

  Note: The order of the events fired ensures that after each event the size described by the ListDataEvents equals the ListModel size.

  Parameters:
    `oldLastIndex` - the last index of the old list
    `newLastIndex` - the last index of the new list

### getSize

    protected static final int getSize(Object aListListModelOrNull)

  Returns the length of the given list, `0` if the list model is `null`.

  Parameters:
    `aListListModelOrNull` - a List, ListModel or null
  Returns:
    the size of the given list, `0` if the list model is `null`

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Copyright © 2002-2011 JGoodies Karsten Lentzsch. All Rights Reserved.