![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.cuf.model.BufferedValueHolder Maven / Gradle / Ivy
The newest version!
package net.sf.cuf.model;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.lang.reflect.Constructor;
/**
* A BufferedValueHolder is a ValueModel that buffers the value
* of a value model.
* The value model being bufferd is called subject, the value model
* triggering the write-back of the buffered value to the subject is
* called trigger.
* The value of the trigger must either be a Boolean, the String
* "true" or "false" or null.
* If the trigger value changes to false, we read the value from
* our subject, if it changes to true, we write the value to our
* subject and if it changes to null, we do nothing.
* We also support the notion of an external update.
* A BufferedValueHolder can also deep-copy it's subjects
* value if the value has a (working) copy constructor.
* @param the type of the value we contain
*/
public class BufferedValueHolder extends AbstractValueModel
implements ValueModel, ExternalUpdate, ChangeListener
{
/** flag if we read from the subject */
public static final Boolean READ_FROM_SUBJECT= Boolean.FALSE;
/** flag if we write to the subject */
public static final Boolean WRITE_TO_SUBJECT = Boolean.TRUE;
/** string for the trigger */
private static final String TRUE = Boolean.TRUE.toString();
/** string for the trigger */
private static final String FALSE= Boolean.FALSE.toString();
/** the ValueModel we buffer, never null */
private ValueModel mSubject;
/** the buffered value of our subject */
private T mBufferedValue;
/** the ValueModel that will cause the write-back (value=true)
* or read-again (value=false), never null */
private ValueModel> mTrigger;
/** marker if we should copy the value of the subject with a copy-constructor */
private boolean mCloneSubjectValue;
/**
* Create a new BufferedValueHolder.
* @param pSubject the subject, must not be null
* @param pTrigger the trigger, must not be null
* @throws IllegalArgumentException if pSubject or pTrigger is null
*/
public BufferedValueHolder(final ValueModel pSubject, final ValueModel> pTrigger)
{
this(pSubject, pTrigger, false);
}
/**
* Create a new BufferedValueHolder.
* @param pSubject the subject, must not be null
* @param pTrigger the trigger, must not be null
* @param pCopySubjectValue true if we should make a deep
* copy via a copy constructor of our subject's value
* @throws IllegalArgumentException if pSubject or pTrigger is null
*/
public BufferedValueHolder(final ValueModel pSubject, final ValueModel> pTrigger, final boolean pCopySubjectValue)
{
super();
if (pSubject==null)
throw new IllegalArgumentException("subject must not be null");
if (pTrigger==null)
throw new IllegalArgumentException("trigger must not be null");
mSubject = pSubject;
mCloneSubjectValue= pCopySubjectValue;
mBufferedValue = getSubjectValue();
mTrigger = pTrigger;
setInSetValue(false, false);
mTrigger.addChangeListener(this);
}
/**
* Returns always true
* @return true
*/
public boolean isEditable()
{
return true;
}
/**
* Cleanup all resources: disconnect from any input sources (like
* other ValueModel's ...), and remove all listeners.
*/
public void dispose()
{
super.dispose();
if (!mTrigger.isDisposed())
{
mTrigger.removeChangeListener(this);
}
}
/**
* Get the subjects value and (if necessary) make a copy of it.
* @return the subject's value
* @throws IllegalArgumentException if the value can't be cloned via
* a copy-constructor
*/
private T getSubjectValue()
{
T value= mSubject.getValue();
if (mCloneSubjectValue && (value!=null))
{
Class extends T> valueClass= (Class extends T>)value.getClass();
try
{
Constructor extends T> constructor= valueClass.getConstructor(valueClass);
value= constructor.newInstance(value);
}
catch (NoSuchMethodException e)
{
throw new IllegalArgumentException("can't clone because copy" +
" constructor is missing: "+
e.getMessage());
}
catch (Exception e)
{
throw new IllegalArgumentException("can't clone value: "+
e.getMessage());
}
}
return value;
}
/**
* Set a new value, this will fire a ChangeEvent if the new value
* is different from the old value.
* @param pValue the new value (null is o.k.)
* @param pIsSetForced true if a forced setValue should be done
* @throws UnsupportedOperationException if this ValueModel is not mutable
*/
public void setValue(final T pValue, final boolean pIsSetForced)
{
checkDisposed();
// optimize only if there is no forced update
if (!pIsSetForced)
{
//noinspection ObjectEquality
if ((mBufferedValue==pValue) ||
(mBufferedValue!= null ? mBufferedValue.equals(pValue) : pValue.equals(mBufferedValue)))
{
// nothing changed
return;
}
}
try
{
setInSetValue(true, pIsSetForced);
mBufferedValue= pValue;
fireStateChanged();
}
finally
{
setInSetValue(false, false);
}
}
/**
* Get the current (buffered) value, during a callback this is the new value.
* @return null or the value object
*/
public T getValue()
{
checkDisposed();
return mBufferedValue;
}
/**
* This method checks if the buffered value is equal to the value
* of our subject.
* @return true if the value of our subject equals our current value
*/
public boolean isBufferEqual()
{
checkDisposed();
Object originalValue= mSubject.getValue();
return (originalValue==null ? (mBufferedValue==null):
originalValue.equals(mBufferedValue));
}
/**
* Invoked when our trigger has changed its state.
*
* @param pEvent a ChangeEvent object
*/
public void stateChanged(final ChangeEvent pEvent)
{
checkDisposed();
if (isInSetValue())
{
throw new IllegalStateException("trigger fired during a setValue()");
}
Object newTriggerValue= mTrigger.getValue();
if (newTriggerValue==null)
{
return;
}
if (!( (newTriggerValue instanceof Boolean) ||
TRUE.equals(newTriggerValue) ||
FALSE.equals(newTriggerValue) ))
{
throw new IllegalArgumentException("boolean value expected, got "+newTriggerValue);
}
boolean doWrite;
if (newTriggerValue instanceof Boolean)
{
doWrite= (Boolean) newTriggerValue;
}
else
{
doWrite= Boolean.valueOf((String) newTriggerValue);
}
if (doWrite)
{
mSubject.setValue(mBufferedValue, mTrigger.isSetForced());
}
else
{
setValue(getSubjectValue(), mTrigger.isSetForced());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy