com.jgoodies.binding.value
Class BufferedValueModel

java.lang.Object
  extended by com.jgoodies.binding.beans.Model
      extended by com.jgoodies.binding.value.AbstractValueModel
          extended by com.jgoodies.binding.value.BufferedValueModel
All Implemented Interfaces:
Observable, ValueModel, java.io.Serializable

public final class BufferedValueModel
extends AbstractValueModel

A ValueModel that wraps another ValueModel, the subject, and delays changes of the subject's value. Returns the subject's value until a value has been set. The buffered value is not written to the subject until the trigger channel changes to Boolean.TRUE. The buffered value can be flushed by changing the trigger channel value to Boolean.FALSE. Note that the commit and flush events are performed only if the trigger channel fires a change event. Since a plain ValueHolder fires no property change event if a value is set that has been set before, it is recommended to use a Trigger instead and invoke its #triggerCommit and triggerFlush methods.

The BufferedValueModel has been designed to behave much like its subject when accessing the value. Therefore it throws all exceptions that would arise when accessing the subject directly. Hence, attempts to read or write a value while the subject is null are always rejected with a NullPointerException.

This class provides the bound read-write properties subject and triggerChannel for the subject and trigger channel and a bound read-only property buffering for the buffering state.

The BufferedValueModel registers listeners with the subject and trigger channel. It is recommended to remove these listeners by invoking #release if the subject and trigger channel live much longer than this buffer. After #release has been called you must not use the BufferedValueModel instance any longer. As an alternative you may use event listener lists in subjects and trigger channels that are based on WeakReferences.

If the subject value changes while this model is in buffering state this change won't show through as this model's new value. If you want to update the value whenever the subject value changes, register a listener with the subject value and flush this model's trigger.

Constraints: The subject is of type Object, the trigger channel value of type Boolean.

Version:
$Revision: 1.11 $
Author:
Karsten Lentzsch
See Also:
ValueModel, ValueModel.getValue(), ValueModel.setValue(Object), Serialized Form

Field Summary
static java.lang.String PROPERTYNAME_BUFFERING
          The name of the bound read-only bean property that indicates whether this models is buffering or in write-through state.
static java.lang.String PROPERTYNAME_SUBJECT
          The name of the bound read-write bean property for the subject.
static java.lang.String PROPERTYNAME_TRIGGER_CHANNEL
          The name of the bound read-write bean property for the trigger channel.
 
Fields inherited from class com.jgoodies.binding.value.AbstractValueModel
PROPERTYNAME_VALUE
 
Constructor Summary
BufferedValueModel(ValueModel subject, ValueModel triggerChannel)
          Constructs a BufferedValueModel on the given subject using the given trigger channel.
 
Method Summary
 ValueModel getSubject()
          Returns the subject, i.e.
 ValueModel getTriggerChannel()
          Returns the ValueModel that is used to trigger commit and flush events.
 java.lang.Object getValue()
          Returns the subject's value if no value has been set since the last commit or flush, and returns the buffered value otherwise.
 boolean isBuffering()
          Returns whether this model buffers a value or not, that is, whether a value has been assigned since the last commit or flush.
 void release()
          Removes the PropertyChangeListeners from the subject and trigger channel.
 void setSubject(ValueModel newSubject)
          Sets a new subject ValueModel, i.e.
 void setTriggerChannel(ValueModel newTriggerChannel)
          Sets the ValueModel that triggers the commit and flush events.
 void setValue(java.lang.Object newBufferedValue)
          Sets a new buffered value and turns this BufferedValueModel into the buffering state.
 
Methods inherited from class com.jgoodies.binding.value.AbstractValueModel
addValueChangeListener, booleanValue, doubleValue, fireValueChange, fireValueChange, fireValueChange, fireValueChange, fireValueChange, fireValueChange, fireValueChange, floatValue, getString, intValue, longValue, removeValueChangeListener, setValue, setValue, setValue, setValue, setValue, toString
 
Methods inherited from class com.jgoodies.binding.beans.Model
addPropertyChangeListener, addPropertyChangeListener, addVetoableChangeListener, addVetoableChangeListener, equals, fireIndexedPropertyChange, fireIndexedPropertyChange, fireIndexedPropertyChange, fireMultiplePropertiesChanged, firePropertyChange, 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, wait, wait, wait
 

Field Detail

PROPERTYNAME_BUFFERING

public static final java.lang.String PROPERTYNAME_BUFFERING
The name of the bound read-only bean property that indicates whether this models is buffering or in write-through state.

See Also:
isBuffering(), Constant Field Values

PROPERTYNAME_SUBJECT

public static final java.lang.String PROPERTYNAME_SUBJECT
The name of the bound read-write bean property for the subject.

See Also:
getSubject(), setSubject(ValueModel), Constant Field Values

PROPERTYNAME_TRIGGER_CHANNEL

public static final java.lang.String PROPERTYNAME_TRIGGER_CHANNEL
The name of the bound read-write bean property for the trigger channel.

See Also:
getTriggerChannel(), setTriggerChannel(ValueModel), Constant Field Values
Constructor Detail

BufferedValueModel

public BufferedValueModel(ValueModel subject,
                          ValueModel triggerChannel)
Constructs a BufferedValueModel on the given subject using the given trigger channel.

Parameters:
subject - the value model to be buffered
triggerChannel - the value model that triggers the commit or flush event
Throws:
java.lang.NullPointerException - if the triggerChannel is null
Method Detail

getSubject

public ValueModel getSubject()
Returns the subject, i.e. the underlying ValueModel that provides the unbuffered value.

Returns:
the ValueModel that provides the unbuffered value

setSubject

public void setSubject(ValueModel newSubject)
Sets a new subject ValueModel, i.e. the model that provides the unbuffered value. Notifies all listeners that the subject property has changed.

Parameters:
newSubject - the subject ValueModel to be set

getTriggerChannel

public ValueModel getTriggerChannel()
Returns the ValueModel that is used to trigger commit and flush events.

Returns:
the ValueModel that is used to trigger commit and flush events

setTriggerChannel

public void setTriggerChannel(ValueModel newTriggerChannel)
Sets the ValueModel that triggers the commit and flush events.

Parameters:
newTriggerChannel - the ValueModel to be set as trigger channel
Throws:
java.lang.NullPointerException - if the newTriggerChannel is null

getValue

public java.lang.Object getValue()
Returns the subject's value if no value has been set since the last commit or flush, and returns the buffered value otherwise. Attempts to read a value when no subject is set are rejected with a NullPointerException.

Returns:
the buffered value
Throws:
java.lang.NullPointerException - if no subject is set

setValue

public void setValue(java.lang.Object newBufferedValue)
Sets a new buffered value and turns this BufferedValueModel into the buffering state. The buffered value is not provided to the underlying model until the trigger channel indicates a commit. Attempts to set a value when no subject is set are rejected with a NullPointerException.

The above semantics is easy to understand, however it is tempting to check the new value against the current subject value to avoid that the buffer unnecessary turns into the buffering state. But here's a problem. Let's say the subject value is "first" at buffer creation time, and let's say the subject value has changed in the meantime to "second". Now someone sets the value "second" to this buffer. The subject value and the value to be set are equal. Shall we buffer? Also, this decision would depend on the ability to read the subject. The semantics would depend on the subject' state and capabilities.

It is often sufficient to observe the buffering state when enabling or disabling a commit command button like "OK" or "Apply". And later check the changed state in a PresentationModel. You may want to do better and may want to observe a property like "defersTrueChange" that indicates whether flushing a buffer will actually change the subject. But note that such a state may change with subject value changes, which may be hard to understand for a user.

TODO: Consider adding an optimized execution path for the case that this model is already in buffering state. In this case the old buffered value can be used instead of invoking #readBufferedOrSubjectValue().

Parameters:
newBufferedValue - the value to be buffered
Throws:
java.lang.NullPointerException - if no subject is set

release

public void release()
Removes the PropertyChangeListeners from the subject and trigger channel.

To avoid memory leaks it is recommended to invoke this method if the subject and trigger channel live much longer than this buffer. Once #release has been invoked the BufferedValueModel instance must not be used any longer.

As an alternative you may use event listener lists in subjects and trigger channels that are based on WeakReferences.

See Also:
WeakReference

isBuffering

public boolean isBuffering()
Returns whether this model buffers a value or not, that is, whether a value has been assigned since the last commit or flush.

Returns:
true if a value has been assigned since the last commit or flush


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