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 simple {@link com.jgoodies.binding.value.ValueModel} implementation
035: * that holds a generic value.
036: * If the value changes, a <code>PropertyChangeEvent</code> is fired
037: * that can be observed using a <code>PropertyChangeListener</code>.<p>
038: *
039: * Differences in the old and new value can be checked either using
040: * <code>==</code> or <code>#equals</code>. The unbound property
041: * <em>identityCheckEnabled</em> determines which mechanism is used
042: * to check for changes in <code>#setValue(Object)</code>.
043: * This check can be overridden for individual changes by the boolean
044: * parameter in <code>#setValue(Object, boolean)</code>.<p>
045: *
046: * <strong>Constraints:</strong> The value is of type <code>Object</code>.
047: *
048: * @author Karsten Lentzsch
049: * @version $Revision: 1.5 $
050: *
051: * @see ValueModel
052: * @see java.beans.PropertyChangeEvent
053: * @see java.beans.PropertyChangeListener
054: * @see com.jgoodies.binding.beans.ExtendedPropertyChangeSupport
055: */
056: public final class ValueHolder extends AbstractValueModel {
057:
058: /**
059: * Holds a value of type <code>Object</code> that is to be observed.
060: */
061: private Object value;
062:
063: /**
064: * Describes whether a value change event shall be fired if the
065: * old and new value are different. If <code>true</code> the old
066: * and new value are compared with <code>==</code>. If <code>false</code>
067: * the values are compared with <code>#equals</code>.
068: *
069: * @see #setValue(Object, boolean)
070: * @see com.jgoodies.binding.beans.Model#firePropertyChange(String, Object, Object, boolean)
071: * @see com.jgoodies.binding.beans.ExtendedPropertyChangeSupport
072: */
073: private boolean checkIdentity;
074:
075: // Instance Creation ****************************************************
076:
077: /**
078: * Constructs a <code>ValueHolder</code> with <code>null</code>
079: * as initial value.
080: */
081: public ValueHolder() {
082: this (null);
083: }
084:
085: /**
086: * Constructs a <code>ValueHolder</code> with the given initial value.
087: * By default the old and new value are compared using <code>#equals</code>
088: * when firing value change events.
089: *
090: * @param initialValue the initial value
091: */
092: public ValueHolder(Object initialValue) {
093: this (initialValue, false);
094: }
095:
096: /**
097: * Constructs a <code>ValueHolder</code> with the given initial value.
098: *
099: * @param initialValue the initial value
100: * @param checkIdentity true to compare the old and new value using
101: * <code>==</code>, false to use <code>#equals</code>
102: */
103: public ValueHolder(Object initialValue, boolean checkIdentity) {
104: value = initialValue;
105: this .checkIdentity = checkIdentity;
106: }
107:
108: /**
109: * Constructs a <code>ValueHolder</code> with the specified initial
110: * boolean value that is converted to a <code>Boolean</code> object.
111: *
112: * @param initialValue the initial boolean value
113: */
114: public ValueHolder(boolean initialValue) {
115: this (Boolean.valueOf(initialValue));
116: }
117:
118: /**
119: * Constructs a <code>ValueHolder</code> with the specified initial
120: * double value that is converted to a <code>Double</code> object.
121: *
122: * @param initialValue the initial double value
123: */
124: public ValueHolder(double initialValue) {
125: this (Double.valueOf(initialValue));
126: }
127:
128: /**
129: * Constructs a <code>ValueHolder</code> with the specified initial
130: * float value that is converted to a <code>Float</code> object.
131: *
132: * @param initialValue the initial float value
133: */
134: public ValueHolder(float initialValue) {
135: this (Float.valueOf(initialValue));
136: }
137:
138: /**
139: * Constructs a <code>ValueHolder</code> with the specified initial
140: * int value that is converted to an <code>Integer</code> object.
141: *
142: * @param initialValue the initial int value
143: */
144: public ValueHolder(int initialValue) {
145: this (Integer.valueOf(initialValue));
146: }
147:
148: /**
149: * Constructs a <code>ValueHolder</code> with the specified initial
150: * long value that is converted to a <code>Long</code> object.
151: *
152: * @param initialValue the initial long value
153: */
154: public ValueHolder(long initialValue) {
155: this (Long.valueOf(initialValue));
156: }
157:
158: // ValueModel Implementation ********************************************
159:
160: /**
161: * Returns the observed value.
162: *
163: * @return the observed value
164: */
165: public Object getValue() {
166: return value;
167: }
168:
169: /**
170: * Sets a new value. Fires a value change event if the old and new
171: * value differ. The difference is tested with <code>==</code> if
172: * <code>isIdentityCheckEnabled</code> answers <code>true</code>.
173: * The values are compared with <code>#equals</code> if the
174: * identity check is disabled.
175: *
176: * @param newValue the new value
177: */
178: public void setValue(Object newValue) {
179: setValue(newValue, isIdentityCheckEnabled());
180: }
181:
182: // Optional Support for Firing Events on Identity Change ***************
183:
184: /**
185: * Answers whether this ValueHolder fires value change events if
186: * and only if the old and new value are not the same.
187: *
188: * @return <code>true</code> if the old and new value are compared
189: * using <code>==</code>, <code>false</code> if the values
190: * are compared using <code>#equals</code>
191: */
192: public boolean isIdentityCheckEnabled() {
193: return checkIdentity;
194: }
195:
196: /**
197: * Sets the comparison that is used to check differences between
198: * the old and new value when firing value change events.
199: * This is the default setting that is used when changing the value via
200: * <code>#setValue(Object)</code>. You can override this default setting
201: * by changing a value via <code>#setValue(Object, boolean)</code>.
202: *
203: * @param checkIdentity true to compare the old and new value using
204: * <code>==</code>, false to use <code>#equals</code>
205: */
206: public void setIdentityCheckEnabled(boolean checkIdentity) {
207: this .checkIdentity = checkIdentity;
208: }
209:
210: /**
211: * Sets a new value. Fires a value change event if the old and new
212: * value differ. The difference is tested with <code>==</code> if
213: * <code>checkIdentity</code> is <code>true</code>. The values are
214: * compared with <code>#equals</code> if the <code>checkIdentiy</code>
215: * parameter is set to <code>false</code>.<p>
216: *
217: * Unlike general bean property setters, this method does not fire
218: * an event if the old and new value are <code>null</code>.
219: *
220: * @param newValue the new value
221: * @param checkIdentity true to compare the old and new value using
222: * <code>==</code>, false to use <code>#equals</code>
223: */
224: public void setValue(Object newValue, boolean checkIdentity) {
225: Object oldValue = getValue();
226: if (oldValue == newValue)
227: return;
228: value = newValue;
229: fireValueChange(oldValue, newValue, checkIdentity);
230: }
231:
232: }
|