source: josm/trunk/src/org/openstreetmap/josm/data/preferences/AbstractProperty.java@ 10824

Last change on this file since 10824 was 10824, checked in by Don-vip, 8 years ago

see #13309 - Caching and notifying preferences (patch by michael2402) - gsoc-core

  • Property svn:eol-style set to native
File size: 9.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.preferences;
3
4import org.openstreetmap.josm.Main;
5import org.openstreetmap.josm.data.Preferences;
6import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
7import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
8
9/**
10 * Captures the common functionality of preference properties
11 * @param <T> The type of object accessed by this property
12 */
13public abstract class AbstractProperty<T> {
14
15 private final class PreferenceChangedListenerAdapter implements PreferenceChangedListener {
16 private ValueChangeListener<? super T> listener;
17
18 PreferenceChangedListenerAdapter(ValueChangeListener<? super T> listener) {
19 this.listener = listener;
20 }
21
22 @Override
23 public void preferenceChanged(PreferenceChangeEvent e) {
24 listener.valueChanged(new ValueChangeEvent<>(e, AbstractProperty.this));
25 }
26
27 @Override
28 public int hashCode() {
29 final int prime = 31;
30 int result = 1;
31 result = prime * result + getOuterType().hashCode();
32 result = prime * result + ((listener == null) ? 0 : listener.hashCode());
33 return result;
34 }
35
36 @Override
37 public boolean equals(Object obj) {
38 if (this == obj)
39 return true;
40 if (obj == null)
41 return false;
42 if (getClass() != obj.getClass())
43 return false;
44 @SuppressWarnings("unchecked")
45 PreferenceChangedListenerAdapter other = (PreferenceChangedListenerAdapter) obj;
46 if (!getOuterType().equals(other.getOuterType()))
47 return false;
48 if (listener == null) {
49 if (other.listener != null)
50 return false;
51 } else if (!listener.equals(other.listener))
52 return false;
53 return true;
54 }
55
56 private AbstractProperty<T> getOuterType() {
57 return AbstractProperty.this;
58 }
59
60 @Override
61 public String toString() {
62 return "PreferenceChangedListenerAdapter [listener=" + listener + ']';
63 }
64 }
65
66 /**
67 * A listener that listens to changes in the properties value.
68 * @author michael
69 * @param <T> property type
70 * @since 10824
71 */
72 public interface ValueChangeListener<T> {
73 /**
74 * Method called when a property value has changed.
75 * @param e property change event
76 */
77 void valueChanged(ValueChangeEvent<? extends T> e);
78 }
79
80 /**
81 * An event that is triggered if the value of a property changes.
82 * @author Michael Zangl
83 * @param <T> property type
84 * @since 10824
85 */
86 public static class ValueChangeEvent<T> {
87 private final PreferenceChangeEvent base;
88
89 private final AbstractProperty<T> source;
90
91 ValueChangeEvent(PreferenceChangeEvent base, AbstractProperty<T> source) {
92 this.base = base;
93 this.source = source;
94 }
95
96 /**
97 * Get the property that was changed
98 * @return The property.
99 */
100 public AbstractProperty<T> getProperty() {
101 return source;
102 }
103 }
104
105 /**
106 * An exception that is thrown if a preference value is invalid.
107 * @author Michael Zangl
108 * @since 10824
109 */
110 public static class InvalidPreferenceValueException extends RuntimeException {
111
112 /**
113 * Constructs a new {@code InvalidPreferenceValueException} with the specified detail message and cause.
114 * @param message the detail message (which is saved for later retrieval by the {@link #getMessage()} method).
115 * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
116 */
117 public InvalidPreferenceValueException(String message, Throwable cause) {
118 super(message, cause);
119 }
120
121 /**
122 * Constructs a new {@code InvalidPreferenceValueException} with the specified detail message.
123 * The cause is not initialized, and may subsequently be initialized by a call to {@link #initCause}.
124 *
125 * @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()} method.
126 */
127 public InvalidPreferenceValueException(String message) {
128 super(message);
129 }
130
131 /**
132 * Constructs a new {@code InvalidPreferenceValueException} with the specified cause and a detail message of
133 * <tt>(cause==null ? null : cause.toString())</tt> (which typically contains the class and detail message of <tt>cause</tt>).
134 *
135 * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
136 */
137 public InvalidPreferenceValueException(Throwable cause) {
138 super(cause);
139 }
140 }
141
142 /**
143 * The preferences object this property is for.
144 */
145 protected final Preferences preferences;
146 protected final String key;
147 protected final T defaultValue;
148
149 /**
150 * Constructs a new {@code AbstractProperty}.
151 * @param key The property key
152 * @param defaultValue The default value
153 * @since 5464
154 */
155 public AbstractProperty(String key, T defaultValue) {
156 // Main.pref should not change in production but may change during tests.
157 preferences = Main.pref;
158 this.key = key;
159 this.defaultValue = defaultValue;
160 }
161
162 /**
163 * Store the default value to {@link Preferences}.
164 */
165 protected void storeDefaultValue() {
166 if (getPreferences() != null) {
167 get();
168 }
169 }
170
171 /**
172 * Replies the property key.
173 * @return The property key
174 */
175 public String getKey() {
176 return key;
177 }
178
179 /**
180 * Determines if this property is currently set in JOSM preferences.
181 * @return true if {@code Main.pref} contains this property.
182 */
183 public boolean isSet() {
184 return !getPreferences().get(key).isEmpty();
185 }
186
187 /**
188 * Replies the default value of this property.
189 * @return The default value of this property
190 */
191 public T getDefaultValue() {
192 return defaultValue;
193 }
194
195 /**
196 * Removes this property from JOSM preferences (i.e replace it by its default value).
197 */
198 public void remove() {
199 put(getDefaultValue());
200 }
201
202 /**
203 * Replies the value of this property.
204 * @return the value of this property
205 * @since 5464
206 */
207 public abstract T get();
208
209 /**
210 * Sets this property to the specified value.
211 * @param value The new value of this property
212 * @return true if something has changed (i.e. value is different than before)
213 * @since 5464
214 */
215 public abstract boolean put(T value);
216
217 /**
218 * Gets the preferences used for this property.
219 * @return The preferences for this property.
220 * @since 10824
221 */
222 protected Preferences getPreferences() {
223 return preferences;
224 }
225
226 /**
227 * Adds a listener that listens only for changes to this preference key.
228 * @param listener The listener to add.
229 * @since 10824
230 */
231 public void addListener(ValueChangeListener<? super T> listener) {
232 addListenerImpl(new PreferenceChangedListenerAdapter(listener));
233 }
234
235 protected void addListenerImpl(PreferenceChangedListener adapter) {
236 getPreferences().addKeyPreferenceChangeListener(getKey(), adapter);
237 }
238
239 /**
240 * Adds a weak listener that listens only for changes to this preference key.
241 * @param listener The listener to add.
242 * @since 10824
243 */
244 public void addWeakListener(ValueChangeListener<? super T> listener) {
245 addWeakListenerImpl(new PreferenceChangedListenerAdapter(listener));
246 }
247
248 protected void addWeakListenerImpl(PreferenceChangedListener adapter) {
249 getPreferences().addWeakKeyPreferenceChangeListener(getKey(), adapter);
250 }
251
252 /**
253 * Removes a listener that listens only for changes to this preference key.
254 * @param listener The listener to add.
255 * @since 10824
256 */
257 public void removeListener(ValueChangeListener<? super T> listener) {
258 removeListenerImpl(new PreferenceChangedListenerAdapter(listener));
259 }
260
261 protected void removeListenerImpl(PreferenceChangedListener adapter) {
262 getPreferences().removeKeyPreferenceChangeListener(getKey(), adapter);
263 }
264
265 @Override
266 public int hashCode() {
267 final int prime = 31;
268 int result = 1;
269 result = prime * result + ((key == null) ? 0 : key.hashCode());
270 result = prime * result + ((preferences == null) ? 0 : preferences.hashCode());
271 return result;
272 }
273
274 @Override
275 public boolean equals(Object obj) {
276 if (this == obj)
277 return true;
278 if (obj == null)
279 return false;
280 if (getClass() != obj.getClass())
281 return false;
282 AbstractProperty<?> other = (AbstractProperty<?>) obj;
283 if (key == null) {
284 if (other.key != null)
285 return false;
286 } else if (!key.equals(other.key))
287 return false;
288 if (preferences == null) {
289 if (other.preferences != null)
290 return false;
291 } else if (!preferences.equals(other.preferences))
292 return false;
293 return true;
294 }
295}
Note: See TracBrowser for help on using the repository browser.