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.adapter;
032:
033: import java.util.prefs.Preferences;
034:
035: import com.jgoodies.binding.value.AbstractValueModel;
036:
037: /**
038: * A ValueModel implementation that reads and writes values from/to a key
039: * of a given <code>Preferences</code> node under a specified key.
040: * Write changes fire value changes.<p>
041: *
042: * <strong>Example:</strong><pre>
043: * String prefsKey = "isShowing";
044: * Boolean defaultValue = Boolean.TRUE;
045: * Preferences prefs = Workbench.userPreferences();
046: * ValueModel model = new PreferencesAdapter(prefs, prefsKey, defaultValue);
047: * JCheckBox showingBox = new JCheckBox("Show tips");
048: * showingBox.setModel(new ToggleButtonAdapter(model));
049: * </pre>
050: *
051: * @author Karsten Lentzsch
052: * @version $Revision: 1.6 $
053: *
054: * @see java.util.prefs.Preferences
055: */
056: public final class PreferencesAdapter extends AbstractValueModel {
057:
058: private static final String ERROR_MSG = "Value must be a Boolean, Double, Float, Integer, Long, or String.";
059:
060: /**
061: * Refers to the preferences node that is used to persist the bound data.
062: */
063: private final Preferences prefs;
064:
065: /**
066: * Holds the preferences key that is used to access the stored value.
067: */
068: private final String key;
069:
070: /**
071: * Refers to the type of accepted values.
072: */
073: private final Class<?> type;
074:
075: /**
076: * Holds the default value that is used if the preferences
077: * do not yet store a value.
078: */
079: private final Object defaultValue;
080:
081: //Instance Creation *******************************************************
082:
083: /**
084: * Constructs a PreferencesAdapter on the given <code>Preferences</code>
085: * using the specified key and default value, all which must be
086: * non-<code>null</code>.
087: *
088: * @param prefs the <code>Preferences</code> used to store and retrieve
089: * @param key the key used to get and set values in the Preferences
090: * @param defaultValue the default value
091: *
092: * @throws NullPointerException if the Preferences, key, or default value
093: * is <code>null</code>
094: * @throws IllegalArgumentException if the default value is of a type other
095: * than Boolean, Double, Float, Integer, Long, or String.
096: */
097: public PreferencesAdapter(Preferences prefs, String key,
098: Object defaultValue) {
099: if (prefs == null)
100: throw new NullPointerException(
101: "The Preferences must not be null.");
102: if (key == null)
103: throw new NullPointerException("The key must not be null.");
104: if (defaultValue == null)
105: throw new NullPointerException(
106: "The default value must not be null.");
107: if (!isBackedType(defaultValue))
108: throw new IllegalArgumentException("The Default "
109: + ERROR_MSG);
110: this .prefs = prefs;
111: this .key = key;
112: this .type = defaultValue.getClass();
113: this .defaultValue = defaultValue;
114: }
115:
116: // ValueModel Implementation **********************************************
117:
118: /**
119: * Looks up and returns the value from the preferences. The value is
120: * look up under this adapter's key. It will be converted before it is
121: * returned.
122: *
123: * @return the retrieved and converted value
124: * @throws ClassCastException if the type of the default value
125: * cannot be read from the preferences
126: */
127: public Object getValue() {
128: if (type == Boolean.class)
129: return Boolean.valueOf(getBoolean());
130: else if (type == Double.class)
131: return Double.valueOf(getDouble());
132: else if (type == Float.class)
133: return Float.valueOf(getFloat());
134: else if (type == Integer.class)
135: return Integer.valueOf(getInt());
136: else if (type == Long.class)
137: return Long.valueOf(getLong());
138: else if (type == String.class)
139: return getString();
140: else
141: throw new ClassCastException(ERROR_MSG);
142: }
143:
144: /**
145: * Converts the given value to a string and puts it into the preferences.
146: *
147: * @param newValue the object to be stored
148: * @throws IllegalArgumentException if the new value cannot be stored
149: * in the preferences due to an illegal type
150: */
151: public void setValue(Object newValue) {
152: if (newValue == null)
153: throw new NullPointerException(
154: "The value must not be null.");
155:
156: // Class valueType = newValue.getClass();
157: // if (type != valueType)
158: // throw new IllegalArgumentException(
159: // "The type of the value set must be consistent "
160: // + "with the default value type " + type);
161: //
162: if (newValue instanceof Boolean)
163: setBoolean(((Boolean) newValue).booleanValue());
164: else if (newValue instanceof Double)
165: setDouble(((Double) newValue).doubleValue());
166: else if (newValue instanceof Float)
167: setFloat(((Float) newValue).floatValue());
168: else if (newValue instanceof Integer)
169: setInt(((Integer) newValue).intValue());
170: else if (newValue instanceof Long)
171: setLong(((Long) newValue).longValue());
172: else if (newValue instanceof String)
173: setString((String) newValue);
174: }
175:
176: // Convenience Accessors **************************************************
177:
178: /**
179: * Looks up, converts and returns the stored value from the preferences.
180: * Returns the default value if no value has been stored before.
181: *
182: * @return the stored value or the default
183: */
184: public boolean getBoolean() {
185: return prefs.getBoolean(key, ((Boolean) defaultValue)
186: .booleanValue());
187: }
188:
189: /**
190: * Looks up, converts and returns the stored value from the preferences.
191: * Returns the default value if no value has been stored before.
192: *
193: * @return the stored value or the default
194: */
195: public double getDouble() {
196: return prefs.getDouble(key, ((Double) defaultValue)
197: .doubleValue());
198: }
199:
200: /**
201: * Looks up, converts and returns the stored value from the preferences.
202: * Returns the default value if no value has been stored before.
203: *
204: * @return the stored value or the default
205: */
206: public float getFloat() {
207: return prefs.getFloat(key, ((Float) defaultValue).floatValue());
208: }
209:
210: /**
211: * Looks up, converts and returns the stored value from the preferences.
212: * Returns the default value if no value has been stored before.
213: *
214: * @return the stored value or the default
215: */
216: public int getInt() {
217: return prefs.getInt(key, ((Integer) defaultValue).intValue());
218: }
219:
220: /**
221: * Looks up, converts and returns the stored value from the preferences.
222: * Returns the default value if no value has been stored before.
223: *
224: * @return the stored value or the default
225: */
226: public long getLong() {
227: return prefs.getLong(key, ((Long) defaultValue).longValue());
228: }
229:
230: /**
231: * Looks up, converts and returns the stored value from the preferences.
232: * Returns the default value if no value has been stored before.
233: *
234: * @return the stored value or the default
235: */
236: @Override
237: public String getString() {
238: return prefs.get(key, (String) defaultValue);
239: }
240:
241: /**
242: * Converts the given value to an Object and stores it in this
243: * adapter's Preferences under this adapter's preferences key.
244: *
245: * @param newValue the value to put into the Preferences
246: *
247: * @throws ClassCastException if the default value is not a Boolean
248: */
249: public void setBoolean(boolean newValue) {
250: boolean oldValue = getBoolean();
251: prefs.putBoolean(key, newValue);
252: fireValueChange(oldValue, newValue);
253: }
254:
255: /**
256: * Converts the given value to an Object and stores it in this
257: * adapter's Preferences under this adapter's preferences key.
258: *
259: * @param newValue the value to put into the Preferences
260: *
261: * @throws ClassCastException if the default value is not a Double
262: */
263: public void setDouble(double newValue) {
264: double oldValue = getDouble();
265: prefs.putDouble(key, newValue);
266: fireValueChange(oldValue, newValue);
267: }
268:
269: /**
270: * Converts the given value to an Object and stores it in this
271: * adapter's Preferences under this adapter's preferences key.
272: *
273: * @param newValue the value to put into the Preferences
274: *
275: * @throws ClassCastException if the default value is not a Float
276: */
277: public void setFloat(float newValue) {
278: float oldValue = getFloat();
279: prefs.putFloat(key, newValue);
280: fireValueChange(oldValue, newValue);
281: }
282:
283: /**
284: * Converts the given value to an Object and stores it in this
285: * adapter's Preferences under this adapter's preferences key.
286: *
287: * @param newValue the value to put into the Preferences
288: *
289: * @throws ClassCastException if the default value is not an Integer
290: */
291: public void setInt(int newValue) {
292: int oldValue = getInt();
293: prefs.putInt(key, newValue);
294: fireValueChange(oldValue, newValue);
295: }
296:
297: /**
298: * Converts the given value to an Object and stores it in this
299: * adapter's Preferences under this adapter's preferences key.
300: *
301: * @param newValue the value to put into the Preferences
302: *
303: * @throws ClassCastException if the default value is not a Long
304: */
305: public void setLong(long newValue) {
306: long oldValue = getLong();
307: prefs.putLong(key, newValue);
308: fireValueChange(oldValue, newValue);
309: }
310:
311: /**
312: * Converts the given value to an Object and stores it in this
313: * adapter's Preferences under this adapter's preferences key.
314: *
315: * @param newValue the value to put into the Preferences
316: *
317: * @throws ClassCastException if the default value is not a String
318: */
319: public void setString(String newValue) {
320: String oldValue = getString();
321: prefs.put(key, newValue);
322: fireValueChange(oldValue, newValue);
323: }
324:
325: // Helper Code ************************************************************
326:
327: /**
328: * Used to check the default value type during construction.
329: */
330: private boolean isBackedType(Object value) {
331: Class<?> aClass = value.getClass();
332: return ((aClass == Boolean.class) || (aClass == Double.class)
333: || (aClass == Float.class) || (aClass == Integer.class)
334: || (aClass == Long.class) || (aClass == String.class));
335: }
336:
337: }
|