Logo Search packages:      
Sourcecode: libjgoodies-binding-java version File versions

com::jgoodies::binding::PresentationModel Class Reference

Inheritance diagram for com::jgoodies::binding::PresentationModel:

com::jgoodies::binding::beans::Model com::jgoodies::binding::beans::Observable com::jgoodies::binding::tutorial::AlbumPresentationModel com::jgoodies::binding::tutorial::basics::ComponentsExample::ExamplePresentationModel com::jgoodies::binding::tutorial::manager::BufferedAlbumPresentationModel

List of all members.

Detailed Description

The standard base class to implement the Presentation Model pattern, that represents the state and behavior of a presentation independently of the GUI components used in the interface. This pattern is described in Martin Fowler's upcoming addition to his "Patterns of Enterprise Application Architecture". More details around this implementation of the Presentation Model pattern and a 3-tier Swing client architecture with a presentation model layer can be found in the JGoodies Binding presentation. This architecture is supported by the JGoodies Binding library. The PresentationModel pattern is known to users of VisualWorks Smalltalk as ApplicationModel.

This class minimizes the effort required to bind, edit, buffer, and observe the bound properties of an exchangeable bean. Therefore it provides five groups of features that are described below:

  1. adapt bean properties,
  2. change the adapted bean,
  3. buffer values,
  4. observe the buffering state, and
  5. track changes in adapted bean properties.

Typically this class will be extended to add custom models, Actions, presentation logic, model operations and other higher-level behavior. However, in simple cases you can use this class as-is. Several methods are intended to be used as-is and a typical subclass should not modify them. For example isChanged, isBuffering, getBean, setBean, getBeanChannel, getModel, getBufferedModel, getTriggerChannel, setTriggerChannel, triggerCommit and triggerFlush.

Adapting Bean Properties
The method getModel(String) vends ValueModels that adapt a bound bean property of an exchangable bean. These ValueModels will be requested from an underlying BeanAdapter. To get such a model you specify the name of the bean property. All properties adapted must be read-write and must comply with the Java Bean coding conventions. In case you need to adapt a read-only or write-only property, or if the bean uses custom names for the reader and writer, use getModel(String, String, String). Also note that you must not mix calls to these methods for the same property name. For details see the JavaDoc class comment in com.jgoodies.binding.beans.BeanAdapter.

Changing the Adapted Bean
The adapted bean is not stored in this PresentationModel. Instead it is held by a ValueModel, the bean channel

PresentationModel fires three PropertyChangeEvents if the bean changes: beforeBean, bean and afterBean. This is useful when sharing a bean channel and you must perform an operation before or after other listeners handle a bean change. Since you cannot rely on the order listeners will be notified, only the beforeBean and afterBean events are guaranteed to be fired before and after the bean change is fired. Note that getBean() returns the new bean before any of these three PropertyChangeEvents is fired. Therefore listeners that handle these events must use the event's old and new value to determine the old and new bean. The order of events fired during a bean change is:

  1. the bean channel fires a value change,
  2. this model fires a beforeBean change,
  3. this model fires the bean change,
  4. this model fires an afterBean change.

Buffering Values
At the core of this feature are the methods getBufferedModel(String) that vend BufferedValueModels that wrap an adapted bean property. The buffer can be commited or flushed using triggerCommit and triggerFlush respectively.

The trigger channel is provided as a bound Java bean property triggerChannel that must be a non-null ValueModel with values of type Boolean. Attempts to read or write other value types may be rejected with runtime exceptions. By default the trigger channel is initialized as an instance of Trigger. As an alternative it can be set in the constructor.

Observing the Buffering State
This class also provides support for observing the buffering state of the BufferedValueModels created with this model. The buffering state is useful for UI actions and operations that are enabled or disabled if there are pending changes, for example on OK or APPLY button. API users can request the buffering state via isBuffering and can observe the bound property buffering.

Tracking Changes in the Adapted Bean
PresentationModel provides support for observing bean property changes and it tracks all changes to report the overall changed state. The latter is useful to detect whether the bean has changed at all, for example to mark the bean as dirty, so it will be updated in a database. API users can request the changed state via isChanged and can observe the bound property changed. If you want to track changes of other ValueModels, bean properties, or of submodels, register them using observeChanged. To reset the changed state invoke resetChanged. In case you track the changed state of submodels you should override resetChanged to reset the changed state in these submodels.

The changed state changes once only (from false to true). If you need instant notifications about changes in the properties of the target bean, you can register PropertyChangeListeners with this model. This is useful if you change the bean and don't want to move your listeners from one bean to the other. And it's useful if you want to observe multiple bean properties at the same time. These listeners are managed by the method set addBeanPropertyChangeListener and removeBeanPropertyChangeListener. Listeners registered via these methods will be removed from the old bean before the bean changes and will be re-added after the new bean has been set. Therefore these listeners will be notified about changes only if the current bean changes a property. They won't be notified if the bean changes - and in turn the property value. If you want to observes property changes caused by bean changes too, register with the adapting ValueModel as returned by getModel(String).

Instance Creation
PresentationModel can be instantiated using four different constructors: you can specify the target bean directly, or you can provide a bean channel to access the bean indirectly. In the latter case you specify a ValueModel that holds the bean that in turn holds the adapted property. In both cases the target bean is accessed indirectly through the bean channel. In both cases you can specify a custom trigger channel, or you can use a default trigger channel.

Note: This PresentationModel provides bound bean properties and you can register and deregister PropertyChangeListers as usual using addPropertyChangeListener and removePropertyChangeListener. Do not mix up the model listeners with the listeners registered with the bean.

Warning: PresentationModels register a PropertyChangeListener with the target bean. Hence, a bean has a reference to all PresentationModels that hold it as target bean. To avoid memory leaks it is recommended to remove this listener if the bean lives much longer than the PresentationModel, enabling the garbage collector to remove the PresentationModel. Setting a PresentationModel's target bean to null removes this listener, which in turn clears the reference from the bean to the PresentationModel. To do so, you can call setBean(null) or set the bean channel's value to null. As an alternative you can use event listener lists in your beans that implement references with WeakReference. Setting the bean to null has side effects, which is fine in most cases. However, you can release all listeners by calling release.

TODO: Further improve the class comment.

TODO: Consider adding a feature to ensure that update notifications are performed in the event dispatch thread. In case the adapted bean is changed in a thread other than the event dispatch thread, such a feature would help complying with Swing's single thread rule. The feature could be implemented by an extended PropertyChangeSupport.

TODO: I plan to improve the support for adapting beans that do not fire PropertyChangeEvents. This affects the classes PropertyAdapter, BeanAdapter, and PresentationModel. Basically the PropertyAdapter and the BeanAdapter's internal SimplePropertyAdapter's shall be able to optionally self-fire a PropertyChangeEvent in case the bean does not. There are several downsides with self-firing events compared to bound bean properties. See Issue 49 for more information about the downsides.

The observeChanges constructor parameter shall be replaced by a more fine-grained choice to not observe (former observeChanges=false), to observe bound properties (former observeChanges=true), and a new setting for self-firing PropertyChangeEvents if a value is set. The latter case may be further splitted up to specify how the self-fired PropertyChangeEvent is created:

  1. oldValue=null, newValue=null
  2. oldValue=null, newValue=the value set
  3. oldValue=value read before the set, newValue=the value set
  4. oldValue=value read before the set, newValue=value read after the set

Karsten Lentzsch

See also:




Definition at line 242 of file PresentationModel.java.

Public Member Functions

synchronized void addBeanPropertyChangeListener (String propertyName, PropertyChangeListener listener)
synchronized void addBeanPropertyChangeListener (PropertyChangeListener listener)
final synchronized void addPropertyChangeListener (String propertyName, PropertyChangeListener listener)
final synchronized void addPropertyChangeListener (PropertyChangeListener listener)
final synchronized void addVetoableChangeListener (String propertyName, VetoableChangeListener listener)
final synchronized void addVetoableChangeListener (VetoableChangeListener listener)
void afterBeanChange (Object oldBean, Object newBean)
void beforeBeanChange (Object oldBean, Object newBean)
Object getBean ()
ValueModel getBeanChannel ()
getBeanPropertyChangeListeners (String propertyName)
getBeanPropertyChangeListeners ()
ComponentValueModel getBufferedComponentModel (String propertyName)
BufferedValueModel getBufferedModel (String propertyName, String getterName, String setterName)
BufferedValueModel getBufferedModel (String propertyName)
Object getBufferedValue (String propertyName)
ComponentValueModel getComponentModel (String propertyName)
AbstractValueModel getModel (String propertyName, String getterName, String setterName)
AbstractValueModel getModel (String propertyName)
final synchronized
getPropertyChangeListeners (String propertyName)
final synchronized
getPropertyChangeListeners ()
ValueModel getTriggerChannel ()
Object getValue (String propertyName)
final synchronized
getVetoableChangeListeners (String propertyName)
final synchronized
getVetoableChangeListeners ()
boolean isBuffering ()
boolean isChanged ()
void observeChanged (ValueModel valueModel)
void observeChanged (Object bean, String propertyName)
 PresentationModel (ValueModel beanChannel, ValueModel triggerChannel)
 PresentationModel (ValueModel beanChannel)
 PresentationModel (Object bean, ValueModel triggerChannel)
 PresentationModel (Object bean)
void release ()
synchronized void removeBeanPropertyChangeListener (String propertyName, PropertyChangeListener listener)
synchronized void removeBeanPropertyChangeListener (PropertyChangeListener listener)
final synchronized void removePropertyChangeListener (String propertyName, PropertyChangeListener listener)
final synchronized void removePropertyChangeListener (PropertyChangeListener listener)
final synchronized void removeVetoableChangeListener (String propertyName, VetoableChangeListener listener)
final synchronized void removeVetoableChangeListener (VetoableChangeListener listener)
void resetChanged ()
void retractInterestFor (ValueModel valueModel)
void retractInterestFor (Object bean, String propertyName)
void setBean (Object newBean)
void setBufferedValue (String propertyName, Object newValue)
void setTriggerChannel (ValueModel newTriggerChannel)
void setValue (String propertyName, Object newValue)
void setVetoableValue (String propertyName, Object newValue) throws PropertyVetoException
void triggerCommit ()
void triggerFlush ()

Static Public Attributes

static final String PROPERTYNAME_AFTER_BEAN = "afterBean"
static final String PROPERTYNAME_BEAN = "bean"
static final String PROPERTYNAME_BEFORE_BEAN = "beforeBean"
static final String PROPERTYNAME_BUFFERING = "buffering"
static final String PROPERTYNAME_CHANGED = "changed"
static final String PROPERTYNAME_TRIGGERCHANNEL = "triggerChannel"

Protected Member Functions

BeanAdapter createBeanAdapter (ValueModel beanChannel)
final boolean equals (Object o1, Object o2)
final void fireMultiplePropertiesChanged ()
final void firePropertyChange (String propertyName, long oldValue, long newValue)
final void firePropertyChange (String propertyName, int oldValue, int newValue)
final void firePropertyChange (String propertyName, float oldValue, float newValue)
final void firePropertyChange (String propertyName, double oldValue, double newValue)
final void firePropertyChange (String propertyName, boolean oldValue, boolean newValue)
final void firePropertyChange (String propertyName, Object oldValue, Object newValue, boolean checkIdentity)
final void firePropertyChange (String propertyName, Object oldValue, Object newValue)
final void firePropertyChange (PropertyChangeEvent event)
final void fireVetoableChange (String propertyName, long oldValue, long newValue) throws PropertyVetoException
final void fireVetoableChange (String propertyName, float oldValue, float newValue) throws PropertyVetoException
final void fireVetoableChange (String propertyName, int oldValue, int newValue) throws PropertyVetoException
final void fireVetoableChange (String propertyName, double oldValue, double newValue) throws PropertyVetoException
final void fireVetoableChange (String propertyName, boolean oldValue, boolean newValue) throws PropertyVetoException
final void fireVetoableChange (String propertyName, Object oldValue, Object newValue) throws PropertyVetoException
final void fireVetoableChange (PropertyChangeEvent event) throws PropertyVetoException
void setChanged (boolean newValue)

Private Member Functions

BufferedValueModel buffer (ValueModel valueModel)
void setBuffering (boolean newValue)
void updateBufferingState (boolean latestBufferingStateChange)

Private Attributes

final BeanAdapter beanAdapter
final Map bufferedComponentModels
boolean buffering = false
final PropertyChangeListener bufferingUpdateHandler
boolean changed = false
final PropertyChangeListener changedUpdateHandler
final Map componentModels
ValueModel triggerChannel
final Map wrappedBuffers


class  BeanChangeHandler
class  BufferingStateHandler
class  UpdateHandler
class  WrappedBuffer

The documentation for this class was generated from the following file:

Generated by  Doxygen 1.6.0   Back to index