Java tutorial
/* * uDig - User Friendly Desktop Internet GIS client * http://udig.refractions.net * (C) 2012, Refractions Research Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD * License v1.0 (http://udig.refractions.net/files/bsd3-v10.html). */ package org.locationtech.udig.catalog; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import org.eclipse.jface.preference.IPersistentPreferenceStore; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; /** * An abstract preference store implementation for remote preference stores. This class is quite * similar to <code>org.eclipse.jface.preference.PreferenceStore</code>, with the exception that it * loads and saves its values from a remote source on startup and shutdown, respectively. * * @author chorner */ public abstract class RemotePreferenceStore implements IPersistentPreferenceStore { /** * List of registered listeners (element type: <code>IPropertyChangeListener</code>). These * listeners are to be informed when the current value of a preference changes. */ private Set<IPropertyChangeListener> listeners = new CopyOnWriteArraySet<IPropertyChangeListener>(); /** * The locally stored copy of the map from preference name to preference value (represented as * strings). */ private Map<String, String> localProperties; /** * The mapping from preference name to default preference value (represented as strings); * <code>null</code> if none. */ private Map<String, String> defaultProperties; /** * Indicates whether a value as been changed by <code>setToDefault</code> or * <code>setValue</code>; initially <code>false</code>. */ private boolean dirty = false; /** * Indicates that the remote store has been initially contacted. */ private boolean ready = false; /** * Obtains the remote value for the specified preference. Subclasses must implement. * * @param name key * @return String value */ protected abstract String getValue(String name); /** * Stores a remote value for the preference with the specified key. Subclasses must implement. */ public abstract void putValue(String name, String value); /** * Determines if the key specified exists in the remote store. * * @param name key of the preference * @return true if key exists */ public abstract boolean isKey(String name); public RemotePreferenceStore() { defaultProperties = new HashMap<String, String>(); localProperties = new HashMap<String, String>(); } /** * This is the initial hit of the remote store. All methods that read or write will check to * ensure we've interacted with the store prior to doing anything. */ protected void load() { // grab all the preferences (initial load so we can detect local modifications) String[] names = preferenceNames(); for (int i = 0; i < names.length; i++) { String value = getValue(names[i]); if (value != null) { localProperties.put(names[i], value); } } ready = true; } public void save() throws IOException { String[] names = preferenceNames(); for (int i = 0; i < names.length; i++) { String remoteValue = getValue(names[i]); String localValue = toString(localProperties.get(names[i])); String defaultValue = toString(defaultProperties.get(names[i])); if (localValue == null) { if (defaultValue == null) { throw new IOException("Default property value not defined"); //$NON-NLS-1$ } else { putValue(names[i], defaultValue); // revert to default } } else if (remoteValue == null) { putValue(names[i], localValue); // first save } else { if (!remoteValue.equals(localValue)) { putValue(names[i], localValue); // regular save } } } dirty = false; } /** * Had to add this method as the Property object was being unreliable in returning its contents * using the getProperty method. We also want null to be null, rather than not "null". */ private String toString(Object object) { if (object == null) return null; if (object instanceof Boolean) { if (((Boolean) object).booleanValue()) { return IPreferenceStore.TRUE; } else { return IPreferenceStore.FALSE; } } return String.valueOf(object); } public void addPropertyChangeListener(IPropertyChangeListener listener) { listeners.add(listener); } public boolean contains(String name) { if (name == null) return false; if (localProperties.containsKey(name) || defaultProperties.containsKey(name)) return true; // check the remote store too Object remoteValue = getValue(name); if (remoteValue == null) return false; else return true; } public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) { // Do we need to fire an event. if ((oldValue == null || !oldValue.equals(newValue))) { final PropertyChangeEvent pe = new PropertyChangeEvent(this, name, oldValue, newValue); for (final IPropertyChangeListener l : listeners) { SafeRunnable.run(new SafeRunnable(JFaceResources.getString("PreferenceStore.changeError")) { //$NON-NLS-1$ public void run() { l.propertyChange(pe); } }); } } } public boolean getBoolean(String name) { if (!ready) load(); return getBoolean(localProperties, name); } private boolean getBoolean(Map<String, String> p, String name) { String value = p != null ? p.get(name) : null; if (value == null) return BOOLEAN_DEFAULT_DEFAULT; if (value.equals(IPreferenceStore.TRUE)) return true; return false; } public boolean getDefaultBoolean(String name) { return getBoolean(defaultProperties, name); } public double getDefaultDouble(String name) { return getDouble(defaultProperties, name); } private double getDouble(Map<String, String> p, String name) { String value = p != null ? p.get(name) : null; if (value == null) return DOUBLE_DEFAULT_DEFAULT; double ival = DOUBLE_DEFAULT_DEFAULT; try { ival = new Double(value).doubleValue(); } catch (NumberFormatException e) { } return ival; } public float getDefaultFloat(String name) { return getFloat(defaultProperties, name); } private float getFloat(Map<String, String> p, String name) { String value = p != null ? p.get(name) : null; if (value == null) return FLOAT_DEFAULT_DEFAULT; float ival = FLOAT_DEFAULT_DEFAULT; try { ival = new Float(value).floatValue(); } catch (NumberFormatException e) { } return ival; } public int getDefaultInt(String name) { return getInt(defaultProperties, name); } private int getInt(Map<String, String> p, String name) { String value = p != null ? p.get(name) : null; if (value == null) return INT_DEFAULT_DEFAULT; int ival = 0; try { ival = Integer.parseInt(value); } catch (NumberFormatException e) { } return ival; } public long getDefaultLong(String name) { return getLong(defaultProperties, name); } private long getLong(Map<String, String> p, String name) { String value = p != null ? p.get(name) : null; if (value == null) return LONG_DEFAULT_DEFAULT; long ival = LONG_DEFAULT_DEFAULT; try { ival = Long.parseLong(value); } catch (NumberFormatException e) { } return ival; } public String getDefaultString(String name) { return getString(defaultProperties, name); } private String getString(Map<String, String> p, String name) { String value = p != null ? p.get(name) : null; if (value == null) return STRING_DEFAULT_DEFAULT; return value; } public double getDouble(String name) { if (!ready) load(); return getDouble(localProperties, name); } public float getFloat(String name) { if (!ready) load(); return getFloat(localProperties, name); } public int getInt(String name) { if (!ready) load(); return getInt(localProperties, name); } public long getLong(String name) { if (!ready) load(); return getLong(localProperties, name); } public String getString(String name) { if (!ready) load(); return getString(localProperties, name); } public boolean isDefault(String name) { // does not check remote store return (!localProperties.containsKey(name) && defaultProperties.containsKey(name)); } public boolean needsSaving() { if (!ready) load(); return dirty; } /** * Returns an enumeration of all preferences known to this store which have current values other * than their default value. * * @return an array of preference names */ public String[] preferenceNames() { Set<String> names = defaultProperties.keySet(); return (String[]) names.toArray(new String[names.size()]); } public void removePropertyChangeListener(IPropertyChangeListener listener) { listeners.remove(listener); } public void setDefault(String name, double value) { setValue(defaultProperties, name, value); } public void setDefault(String name, float value) { setValue(defaultProperties, name, value); } public void setDefault(String name, int value) { setValue(defaultProperties, name, value); } public void setDefault(String name, long value) { setValue(defaultProperties, name, value); } public void setDefault(String name, String value) { setValue(defaultProperties, name, value); } public void setDefault(String name, boolean value) { setValue(defaultProperties, name, value); } private void setValue(Map<String, String> p, String name, double value) { Assert.isTrue(p != null && name != null); p.put(name, toString(new Double(value))); } private void setValue(Map<String, String> p, String name, float value) { Assert.isTrue(p != null && name != null); p.put(name, toString(new Float(value))); } private void setValue(Map<String, String> p, String name, int value) { Assert.isTrue(p != null && name != null); p.put(name, toString(Integer.valueOf(value))); } private void setValue(Map<String, String> p, String name, long value) { Assert.isTrue(p != null && name != null); p.put(name, toString(Long.valueOf(value))); } private void setValue(Map<String, String> p, String name, String value) { Assert.isTrue(p != null && name != null && value != null); p.put(name, value); } private void setValue(Map<String, String> p, String name, boolean value) { Assert.isTrue(p != null && name != null); p.put(name, toString(Boolean.valueOf(value))); } public void setToDefault(String name) { Object oldValue = localProperties.get(name); localProperties.remove(name); dirty = true; Object newValue = null; if (defaultProperties != null) newValue = defaultProperties.get(name); firePropertyChangeEvent(name, oldValue, newValue); } public void setValue(String name, double value) { double oldValue = getDouble(name); if (oldValue != value) { setValue(localProperties, name, value); dirty = true; firePropertyChangeEvent(name, new Double(oldValue), new Double(value)); } } public void setValue(String name, float value) { float oldValue = getFloat(name); if (oldValue != value) { setValue(localProperties, name, value); dirty = true; firePropertyChangeEvent(name, new Float(oldValue), new Float(value)); } } public void setValue(String name, int value) { int oldValue = getInt(name); if (oldValue != value) { setValue(localProperties, name, value); dirty = true; firePropertyChangeEvent(name, Integer.valueOf(oldValue), Integer.valueOf(value)); } } public void setValue(String name, long value) { long oldValue = getLong(name); if (oldValue != value) { setValue(localProperties, name, value); dirty = true; firePropertyChangeEvent(name, Long.valueOf(oldValue), Long.valueOf(value)); } } public void setValue(String name, String value) { String oldValue = getString(name); if (oldValue == null || !oldValue.equals(value)) { setValue(localProperties, name, value); dirty = true; firePropertyChangeEvent(name, oldValue, value); } } public void setValue(String name, boolean value) { boolean oldValue = getBoolean(name); if (oldValue != value) { setValue(localProperties, name, value); dirty = true; firePropertyChangeEvent(name, Boolean.valueOf(oldValue), Boolean.valueOf(value)); } } }