001: /*
002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.binding.value;
032:
033: /**
034: * A ValueModel implementation that is intended to be used as trigger channel
035: * for instances of BufferedValueModel. API users shall trigger commit and flush
036: * events using <code>#triggerCommit</code> and <code>#triggerFlush</code>.<p>
037: *
038: * This Trigger class works around an inconvenient situation when using
039: * a general ValueHolder as trigger channel of a BufferedValueModel.
040: * BufferedValueHolder performs commit and flush events only if the trigger
041: * channel value reports a change. And a ValueHolder doesn't report a change
042: * if <code>#setValue</code> tries to set the current value. For example
043: * if you set <code>Boolean.TRUE</code> twice, the latter doesn't fire
044: * a property change event. The methods <code>#triggerCommit</code> and
045: * <code>#triggerFlush</code> check for the current state and guarantee
046: * that the appropriate <code>PropertyChangeEvent</code> is fired.
047: * On the other hand, the implementation minimizes the number of events
048: * necessary to commit or flush buffered values.<p>
049: *
050: * <strong>Constraints:</strong> The value is of type <code>Boolean</code>.
051: * <p>
052: * The following example delays the commit of a buffered value:
053: * <pre>
054: * ValueModel subject = new ValueHolder();
055: * Trigger trigger = new Trigger();
056: * BufferedValueModel buffer = new BufferedValueModel(subject, trigger);
057: *
058: * buffer.setValue("value");
059: * ...
060: * trigger.triggerCommit();
061: * </pre>
062: *
063: * @author Karsten Lentzsch
064: * @version $Revision: 1.5 $
065: *
066: * @see BufferedValueModel
067: */
068: public final class Trigger extends AbstractValueModel {
069:
070: private static final Boolean COMMIT = Boolean.TRUE;
071: private static final Boolean FLUSH = Boolean.FALSE;
072: private static final Boolean NEUTRAL = null;
073:
074: /**
075: * Holds the current trigger state.
076: */
077: private Boolean value;
078:
079: // Instance Creation ******************************************************
080:
081: /**
082: * Constructs a Trigger set to neutral.
083: */
084: public Trigger() {
085: value = NEUTRAL;
086: }
087:
088: // ValueModel Implementation **********************************************
089:
090: /**
091: * Returns a Boolean that indicates the current trigger state.
092: *
093: * @return a Boolean that indicates the current trigger state
094: */
095: public Object getValue() {
096: return value;
097: }
098:
099: /**
100: * Sets a new Boolean value and rejects all non-Boolean values.
101: * Fires no change event if the new value is equal to the
102: * previously set value.<p>
103: *
104: * This method is not intended to be used by API users.
105: * Instead you should trigger commit and flush events by invoking
106: * <code>#triggerCommit</code> or <code>#triggerFlush</code>.
107: *
108: * @param newValue the Boolean value to be set
109: * @throws IllegalArgumentException if the newValue is not a Boolean
110: */
111: public void setValue(Object newValue) {
112: if ((newValue != null) && !(newValue instanceof Boolean))
113: throw new IllegalArgumentException(
114: "Trigger values must be of type Boolean.");
115:
116: Object oldValue = value;
117: value = (Boolean) newValue;
118: fireValueChange(oldValue, newValue);
119: }
120:
121: // Triggering *************************************************************
122:
123: /**
124: * Triggers a commit event in BufferedValueModels that share this Trigger.
125: * Sets the value to <code>Boolean.TRUE</code> and ensures that listeners
126: * are notified about a value change to this new value. If necessary
127: * the value is temporarily set to <code>null</code>. This way it minimizes
128: * the number of PropertyChangeEvents fired by this Trigger.
129: */
130: public void triggerCommit() {
131: if (COMMIT.equals(getValue()))
132: setValue(NEUTRAL);
133: setValue(COMMIT);
134: }
135:
136: /**
137: * Triggers a flush event in BufferedValueModels that share this Trigger.
138: * Sets the value to <code>Boolean.FALSE</code> and ensures that listeners
139: * are notified about a value change to the new value. If necessary
140: * the value is temporarily set to <code>null</code>. This way it minimizes
141: * the number of PropertyChangeEvents fired by this Trigger.
142: */
143: public void triggerFlush() {
144: if (FLUSH.equals(getValue()))
145: setValue(NEUTRAL);
146: setValue(FLUSH);
147: }
148:
149: }
|