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

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

sonar - squid:S1609 - @FunctionalInterface annotation should be used to flag Single Abstract Method interfaces

  • 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 final 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 @FunctionalInterface
73 public interface ValueChangeListener<T> {
74 /**
75 * Method called when a property value has changed.
76 * @param e property change event
77 */
78 void valueChanged(ValueChangeEvent<? extends T> e);
79 }
80
81 /**
82 * An event that is triggered if the value of a property changes.
83 * @author Michael Zangl
84 * @param <T> property type
85 * @since 10824
86 */
87 public static class ValueChangeEvent<T> {
88 private final PreferenceChangeEvent base;
89
90 private final AbstractProperty<T> source;
91
92 ValueChangeEvent(PreferenceChangeEvent base, AbstractProperty<T> source) {
93 this.base = base;
94 this.source = source;
95 }
96
97 /**
98 * Get the property that was changed
99 * @return The property.
100 */
101 public AbstractProperty<T> getProperty() {
102 return source;
103 }
104 }
105
106 /**
107 * An exception that is thrown if a preference value is invalid.
108 * @author Michael Zangl
109 * @since 10824
110 */
111 public static class InvalidPreferenceValueException extends RuntimeException {
112
113 /**
114 * Constructs a new {@code InvalidPreferenceValueException} with the specified detail message and cause.
115 * @param message the detail message (which is saved for later retrieval by the {@link #getMessage()} method).
116 * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
117 */
118 public InvalidPreferenceValueException(String message, Throwable cause) {
119 super(message, cause);
120 }
121
122 /**
123 * Constructs a new {@code InvalidPreferenceValueException} with the specified detail message.
124 * The cause is not initialized, and may subsequently be initialized by a call to {@link #initCause}.
125 *
126 * @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()} method.
127 */
128 public InvalidPreferenceValueException(String message) {
129 super(message);
130 }
131
132 /**
133 * Constructs a new {@code InvalidPreferenceValueException} with the specified cause and a detail message of
134 * <tt>(cause==null ? null : cause.toString())</tt> (which typically contains the class and detail message of <tt>cause</tt>).
135 *
136 * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
137 */
138 public InvalidPreferenceValueException(Throwable cause) {
139 super(cause);
140 }
141 }
142
143 /**
144 * The preferences object this property is for.
145 */
146 protected final Preferences preferences;
147 protected final String key;
148 protected final T defaultValue;
149
150 /**
151 * Constructs a new {@code AbstractProperty}.
152 * @param key The property key
153 * @param defaultValue The default value
154 * @since 5464
155 */
156 public AbstractProperty(String key, T defaultValue) {
157 // Main.pref should not change in production but may change during tests.
158 preferences = Main.pref;
159 this.key = key;
160 this.defaultValue = defaultValue;
161 }
162
163 /**
164 * Store the default value to {@link Preferences}.
165 */
166 protected void storeDefaultValue() {
167 if (getPreferences() != null) {
168 get();
169 }
170 }
171
172 /**
173 * Replies the property key.
174 * @return The property key
175 */
176 public String getKey() {
177 return key;
178 }
179
180 /**
181 * Determines if this property is currently set in JOSM preferences.
182 * @return true if {@code Main.pref} contains this property.
183 */
184 public boolean isSet() {
185 return !getPreferences().get(key).isEmpty();
186 }
187
188 /**
189 * Replies the default value of this property.
190 * @return The default value of this property
191 */
192 public T getDefaultValue() {
193 return defaultValue;
194 }
195
196 /**
197 * Removes this property from JOSM preferences (i.e replace it by its default value).
198 */
199 public void remove() {
200 put(getDefaultValue());
201 }
202
203 /**
204 * Replies the value of this property.
205 * @return the value of this property
206 * @since 5464
207 */
208 public abstract T get();
209
210 /**
211 * Sets this property to the specified value.
212 * @param value The new value of this property
213 * @return true if something has changed (i.e. value is different than before)
214 * @since 5464
215 */
216 public abstract boolean put(T value);
217
218 /**
219 * Gets the preferences used for this property.
220 * @return The preferences for this property.
221 * @since 10824
222 */
223 protected Preferences getPreferences() {
224 return preferences;
225 }
226
227 /**
228 * Adds a listener that listens only for changes to this preference key.
229 * @param listener The listener to add.
230 * @since 10824
231 */
232 public void addListener(ValueChangeListener<? super T> listener) {
233 addListenerImpl(new PreferenceChangedListenerAdapter(listener));
234 }
235
236 protected void addListenerImpl(PreferenceChangedListener adapter) {
237 getPreferences().addKeyPreferenceChangeListener(getKey(), adapter);
238 }
239
240 /**
241 * Adds a weak listener that listens only for changes to this preference key.
242 * @param listener The listener to add.
243 * @since 10824
244 */
245 public void addWeakListener(ValueChangeListener<? super T> listener) {
246 addWeakListenerImpl(new PreferenceChangedListenerAdapter(listener));
247 }
248
249 protected void addWeakListenerImpl(PreferenceChangedListener adapter) {
250 getPreferences().addWeakKeyPreferenceChangeListener(getKey(), adapter);
251 }
252
253 /**
254 * Removes a listener that listens only for changes to this preference key.
255 * @param listener The listener to add.
256 * @since 10824
257 */
258 public void removeListener(ValueChangeListener<? super T> listener) {
259 removeListenerImpl(new PreferenceChangedListenerAdapter(listener));
260 }
261
262 protected void removeListenerImpl(PreferenceChangedListener adapter) {
263 getPreferences().removeKeyPreferenceChangeListener(getKey(), adapter);
264 }
265
266 @Override
267 public int hashCode() {
268 final int prime = 31;
269 int result = 1;
270 result = prime * result + ((key == null) ? 0 : key.hashCode());
271 result = prime * result + ((preferences == null) ? 0 : preferences.hashCode());
272 return result;
273 }
274
275 @Override
276 public boolean equals(Object obj) {
277 if (this == obj)
278 return true;
279 if (obj == null)
280 return false;
281 if (getClass() != obj.getClass())
282 return false;
283 AbstractProperty<?> other = (AbstractProperty<?>) obj;
284 if (key == null) {
285 if (other.key != null)
286 return false;
287 } else if (!key.equals(other.key))
288 return false;
289 if (preferences == null) {
290 if (other.preferences != null)
291 return false;
292 } else if (!preferences.equals(other.preferences))
293 return false;
294 return true;
295 }
296}
Note: See TracBrowser for help on using the repository browser.