Remove unused method.
[Sone.git] / src / main / java / net / pterodactylus / sone / core / Options.java
1 /*
2  * Sone - Options.java - Copyright © 2010–2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.core;
19
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import com.google.common.base.Predicate;
25
26 /**
27  * Stores various options that influence Sone’s behaviour.
28  *
29  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
30  */
31 public class Options {
32
33         /**
34          * Contains current and default value of an option.
35          *
36          * @param <T>
37          *            The type of the option
38          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
39          */
40         public static interface Option<T> {
41
42                 /**
43                  * Returns the current value of the option. If the current value is not
44                  * set (usually {@code null}), the default value is returned.
45                  *
46                  * @return The current value of the option
47                  */
48                 public T get();
49
50                 /**
51                  * Returns the real value of the option. This will also return an unset
52                  * value (usually {@code null})!
53                  *
54                  * @return The real value of the option
55                  */
56                 public T getReal();
57
58                 /**
59                  * Validates the given value. Note that {@code null} is always a valid
60                  * value!
61                  *
62                  * @param value
63                  *            The value to validate
64                  * @return {@code true} if this option does not have a validator, or the
65                  *         validator validates this object, {@code false} otherwise
66                  */
67                 public boolean validate(T value);
68
69                 /**
70                  * Sets the current value of the option.
71                  *
72                  * @param value
73                  *            The new value of the option
74                  * @throws IllegalArgumentException
75                  *             if the value is not valid for this option
76                  */
77                 public void set(T value) throws IllegalArgumentException;
78
79         }
80
81         /**
82          * Interface for objects that want to be notified when an option changes its
83          * value.
84          *
85          * @param <T>
86          *            The type of the option
87          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
88          */
89         public static interface OptionWatcher<T> {
90
91                 /**
92                  * Notifies an object that an option has been changed.
93                  *
94                  * @param option
95                  *            The option that has changed
96                  * @param oldValue
97                  *            The old value of the option
98                  * @param newValue
99                  *            The new value of the option
100                  */
101                 public void optionChanged(Option<T> option, T oldValue, T newValue);
102
103         }
104
105         /**
106          * Basic implementation of an {@link Option} that notifies an
107          * {@link OptionWatcher} if the value changes.
108          *
109          * @param <T>
110          *            The type of the option
111          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
112          */
113         public static class DefaultOption<T> implements Option<T> {
114
115                 /** The default value. */
116                 private final T defaultValue;
117
118                 /** The current value. */
119                 private volatile T value;
120
121                 /** The validator. */
122                 private Predicate<T> validator;
123
124                 /** The option watcher. */
125                 private final OptionWatcher<T> optionWatcher;
126
127                 /**
128                  * Creates a new default option.
129                  *
130                  * @param defaultValue
131                  *            The default value of the option
132                  */
133                 public DefaultOption(T defaultValue) {
134                         this(defaultValue, (OptionWatcher<T>) null);
135                 }
136
137                 /**
138                  * Creates a new default option.
139                  *
140                  * @param defaultValue
141                  *            The default value of the option
142                  * @param validator
143                  *            The validator for value validation (may be {@code null})
144                  */
145                 public DefaultOption(T defaultValue, Predicate<T> validator) {
146                         this(defaultValue, validator, null);
147                 }
148
149                 /**
150                  * Creates a new default option.
151                  *
152                  * @param defaultValue
153                  *            The default value of the option
154                  * @param optionWatchers
155                  *            The option watchers (may be {@code null})
156                  */
157                 public DefaultOption(T defaultValue, OptionWatcher<T> optionWatchers) {
158                         this(defaultValue, null, optionWatchers);
159                 }
160
161                 /**
162                  * Creates a new default option.
163                  *
164                  * @param defaultValue
165                  *            The default value of the option
166                  * @param validator
167                  *            The validator for value validation (may be {@code null})
168                  * @param optionWatcher
169                  *            The option watcher (may be {@code null})
170                  */
171                 public DefaultOption(T defaultValue, Predicate<T> validator, OptionWatcher<T> optionWatcher) {
172                         this.defaultValue = defaultValue;
173                         this.validator = validator;
174                         this.optionWatcher = optionWatcher;
175                 }
176
177                 /**
178                  * {@inheritDoc}
179                  */
180                 @Override
181                 public T get() {
182                         return (value != null) ? value : defaultValue;
183                 }
184
185                 /**
186                  * Returns the real value of the option. This will also return an unset
187                  * value (usually {@code null})!
188                  *
189                  * @return The real value of the option
190                  */
191                 @Override
192                 public T getReal() {
193                         return value;
194                 }
195
196                 /**
197                  * {@inheritDoc}
198                  */
199                 @Override
200                 public boolean validate(T value) {
201                         return (validator == null) || (value == null) || validator.apply(value);
202                 }
203
204                 /**
205                  * {@inheritDoc}
206                  */
207                 @Override
208                 public void set(T value) {
209                         if ((value != null) && (validator != null) && (!validator.apply(value))) {
210                                 throw new IllegalArgumentException("New Value (" + value + ") could not be validated.");
211                         }
212                         T oldValue = this.value;
213                         this.value = value;
214                         if (!get().equals(oldValue)) {
215                                 if (optionWatcher != null) {
216                                         optionWatcher.optionChanged(this, oldValue, get());
217                                 }
218                         }
219                 }
220
221         }
222
223         /** Holds all {@link Boolean} {@link Option}s. */
224         private final Map<String, Option<Boolean>> booleanOptions = Collections.synchronizedMap(new HashMap<String, Option<Boolean>>());
225
226         /** Holds all {@link Integer} {@link Option}s. */
227         private final Map<String, Option<Integer>> integerOptions = Collections.synchronizedMap(new HashMap<String, Option<Integer>>());
228
229         /** Holds all {@link String} {@link Option}s. */
230         private final Map<String, Option<String>> stringOptions = Collections.synchronizedMap(new HashMap<String, Option<String>>());
231
232         /** Holds all {@link Enum} {@link Option}s. */
233         private final Map<String, Option<? extends Enum<?>>> enumOptions = Collections.synchronizedMap(new HashMap<String, Option<? extends Enum<?>>>());
234
235         /**
236          * Adds a boolean option.
237          *
238          * @param name
239          *            The name of the option
240          * @param booleanOption
241          *            The option
242          * @return The given option
243          */
244         public Option<Boolean> addBooleanOption(String name, Option<Boolean> booleanOption) {
245                 booleanOptions.put(name, booleanOption);
246                 return booleanOption;
247         }
248
249         /**
250          * Returns the boolean option with the given name.
251          *
252          * @param name
253          *            The name of the option
254          * @return The option, or {@code null} if there is no option with the given
255          *         name
256          */
257         public Option<Boolean> getBooleanOption(String name) {
258                 return booleanOptions.get(name);
259         }
260
261         /**
262          * Adds an {@link Integer} {@link Option}.
263          *
264          * @param name
265          *            The name of the option
266          * @param integerOption
267          *            The option
268          * @return The given option
269          */
270         public Option<Integer> addIntegerOption(String name, Option<Integer> integerOption) {
271                 integerOptions.put(name, integerOption);
272                 return integerOption;
273         }
274
275         /**
276          * Returns an {@link Integer} {@link Option}.
277          *
278          * @param name
279          *            The name of the integer option to get
280          * @return The integer option, or {@code null} if there is no option with
281          *         the given name
282          */
283         public Option<Integer> getIntegerOption(String name) {
284                 return integerOptions.get(name);
285         }
286
287         /**
288          * Adds a {@link String} {@link Option}.
289          *
290          * @param name
291          *            The name of the option
292          * @param stringOption
293          *            The option
294          * @return The given option
295          */
296         public Option<String> addStringOption(String name, Option<String> stringOption) {
297                 stringOptions.put(name, stringOption);
298                 return stringOption;
299         }
300
301         /**
302          * Returns a {@link String} {@link Option}.
303          *
304          * @param name
305          *            The name of the string option to get
306          * @return The string option, or {@code null} if there is no option with the
307          *         given name
308          */
309         public Option<String> getStringOption(String name) {
310                 return stringOptions.get(name);
311         }
312
313         /**
314          * Adds an {@link Enum} {@link Option}.
315          *
316          * @param <T>
317          *            The enum type
318          * @param name
319          *            The name of the option
320          * @param enumOption
321          *            The option
322          * @return The given option
323          */
324         public <T extends Enum<T>> Option<T> addEnumOption(String name, Option<T> enumOption) {
325                 enumOptions.put(name, enumOption);
326                 return enumOption;
327         }
328
329         /**
330          * Returns a {@link Enum} {@link Option}. As the type can probably not be
331          * interred correctly you could help the compiler by calling this method
332          * like this:
333          * <p>
334          *
335          * <pre>
336          * options.&lt;SomeEnum&gt; getEnumOption(&quot;SomeEnumOption&quot;).get();
337          * </pre>
338          *
339          * @param <T>
340          *            The enum type
341          * @param name
342          *            The name of the option
343          * @return The enum option, or {@code null} if there is no enum option with
344          *         the given name
345          */
346         @SuppressWarnings("unchecked")
347         public <T extends Enum<T>> Option<T> getEnumOption(String name) {
348                 return (Option<T>) enumOptions.get(name);
349         }
350
351 }