All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 valueClass= (Class)value.getClass(); try { Constructor 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