Remove option watcher, it’s not used anymore.
[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          * Basic implementation of an {@link Option}.
83          *
84          * @param <T>
85          *            The type of the option
86          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
87          */
88         public static class DefaultOption<T> implements Option<T> {
89
90                 /** The default value. */
91                 private final T defaultValue;
92
93                 /** The current value. */
94                 private volatile T value;
95
96                 /** The validator. */
97                 private Predicate<T> validator;
98
99                 /**
100                  * Creates a new default option.
101                  *
102                  * @param defaultValue
103                  *            The default value of the option
104                  */
105                 public DefaultOption(T defaultValue) {
106                         this(defaultValue, null);
107                 }
108
109                 /**
110                  * Creates a new default option.
111                  *
112                  * @param defaultValue
113                  *            The default value of the option
114                  * @param validator
115                  *            The validator for value validation (may be {@code null})
116                  */
117                 public DefaultOption(T defaultValue, Predicate<T> validator) {
118                         this.defaultValue = defaultValue;
119                         this.validator = validator;
120                 }
121
122                 /**
123                  * {@inheritDoc}
124                  */
125                 @Override
126                 public T get() {
127                         return (value != null) ? value : defaultValue;
128                 }
129
130                 /**
131                  * Returns the real value of the option. This will also return an unset
132                  * value (usually {@code null})!
133                  *
134                  * @return The real value of the option
135                  */
136                 @Override
137                 public T getReal() {
138                         return value;
139                 }
140
141                 /**
142                  * {@inheritDoc}
143                  */
144                 @Override
145                 public boolean validate(T value) {
146                         return (validator == null) || (value == null) || validator.apply(value);
147                 }
148
149                 /**
150                  * {@inheritDoc}
151                  */
152                 @Override
153                 public void set(T value) {
154                         if ((value != null) && (validator != null) && (!validator.apply(value))) {
155                                 throw new IllegalArgumentException("New Value (" + value + ") could not be validated.");
156                         }
157                         T oldValue = this.value;
158                         this.value = value;
159                 }
160
161         }
162
163         /** Holds all {@link Boolean} {@link Option}s. */
164         private final Map<String, Option<Boolean>> booleanOptions = Collections.synchronizedMap(new HashMap<String, Option<Boolean>>());
165
166         /** Holds all {@link Integer} {@link Option}s. */
167         private final Map<String, Option<Integer>> integerOptions = Collections.synchronizedMap(new HashMap<String, Option<Integer>>());
168
169         /** Holds all {@link String} {@link Option}s. */
170         private final Map<String, Option<String>> stringOptions = Collections.synchronizedMap(new HashMap<String, Option<String>>());
171
172         /** Holds all {@link Enum} {@link Option}s. */
173         private final Map<String, Option<? extends Enum<?>>> enumOptions = Collections.synchronizedMap(new HashMap<String, Option<? extends Enum<?>>>());
174
175         /**
176          * Adds a boolean option.
177          *
178          * @param name
179          *            The name of the option
180          * @param booleanOption
181          *            The option
182          * @return The given option
183          */
184         public Option<Boolean> addBooleanOption(String name, Option<Boolean> booleanOption) {
185                 booleanOptions.put(name, booleanOption);
186                 return booleanOption;
187         }
188
189         /**
190          * Returns the boolean option with the given name.
191          *
192          * @param name
193          *            The name of the option
194          * @return The option, or {@code null} if there is no option with the given
195          *         name
196          */
197         public Option<Boolean> getBooleanOption(String name) {
198                 return booleanOptions.get(name);
199         }
200
201         /**
202          * Adds an {@link Integer} {@link Option}.
203          *
204          * @param name
205          *            The name of the option
206          * @param integerOption
207          *            The option
208          * @return The given option
209          */
210         public Option<Integer> addIntegerOption(String name, Option<Integer> integerOption) {
211                 integerOptions.put(name, integerOption);
212                 return integerOption;
213         }
214
215         /**
216          * Returns an {@link Integer} {@link Option}.
217          *
218          * @param name
219          *            The name of the integer option to get
220          * @return The integer option, or {@code null} if there is no option with
221          *         the given name
222          */
223         public Option<Integer> getIntegerOption(String name) {
224                 return integerOptions.get(name);
225         }
226
227         /**
228          * Adds a {@link String} {@link Option}.
229          *
230          * @param name
231          *            The name of the option
232          * @param stringOption
233          *            The option
234          * @return The given option
235          */
236         public Option<String> addStringOption(String name, Option<String> stringOption) {
237                 stringOptions.put(name, stringOption);
238                 return stringOption;
239         }
240
241         /**
242          * Returns a {@link String} {@link Option}.
243          *
244          * @param name
245          *            The name of the string option to get
246          * @return The string option, or {@code null} if there is no option with the
247          *         given name
248          */
249         public Option<String> getStringOption(String name) {
250                 return stringOptions.get(name);
251         }
252
253         /**
254          * Adds an {@link Enum} {@link Option}.
255          *
256          * @param <T>
257          *            The enum type
258          * @param name
259          *            The name of the option
260          * @param enumOption
261          *            The option
262          * @return The given option
263          */
264         public <T extends Enum<T>> Option<T> addEnumOption(String name, Option<T> enumOption) {
265                 enumOptions.put(name, enumOption);
266                 return enumOption;
267         }
268
269         /**
270          * Returns a {@link Enum} {@link Option}. As the type can probably not be
271          * interred correctly you could help the compiler by calling this method
272          * like this:
273          * <p>
274          *
275          * <pre>
276          * options.&lt;SomeEnum&gt; getEnumOption(&quot;SomeEnumOption&quot;).get();
277          * </pre>
278          *
279          * @param <T>
280          *            The enum type
281          * @param name
282          *            The name of the option
283          * @return The enum option, or {@code null} if there is no enum option with
284          *         the given name
285          */
286         @SuppressWarnings("unchecked")
287         public <T extends Enum<T>> Option<T> getEnumOption(String name) {
288                 return (Option<T>) enumOptions.get(name);
289         }
290
291 }