Merge branch 'release-0.6.2'
[Sone.git] / src / main / java / net / pterodactylus / sone / core / Options.java
1 /*
2  * Sone - Options.java - Copyright © 2010 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.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 /**
28  * Stores various options that influence Sone’s behaviour.
29  *
30  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
31  */
32 public class Options {
33
34         /**
35          * Contains current and default value of an option.
36          *
37          * @param <T>
38          *            The type of the option
39          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
40          */
41         public static interface Option<T> {
42
43                 /**
44                  * Returns the default value of the option.
45                  *
46                  * @return The default value of the option
47                  */
48                 public T getDefault();
49
50                 /**
51                  * Returns the current value of the option. If the current value is not
52                  * set (usually {@code null}), the default value is returned.
53                  *
54                  * @return The current value of the option
55                  */
56                 public T get();
57
58                 /**
59                  * Returns the real value of the option. This will also return an unset
60                  * value (usually {@code null})!
61                  *
62                  * @return The real value of the option
63                  */
64                 public T getReal();
65
66                 /**
67                  * Sets the current value of the option.
68                  *
69                  * @param value
70                  *            The new value of the option
71                  */
72                 public void set(T value);
73
74         }
75
76         /**
77          * Interface for objects that want to be notified when an option changes its
78          * value.
79          *
80          * @param <T>
81          *            The type of the option
82          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
83          */
84         public static interface OptionWatcher<T> {
85
86                 /**
87                  * Notifies an object that an option has been changed.
88                  *
89                  * @param option
90                  *            The option that has changed
91                  * @param oldValue
92                  *            The old value of the option
93                  * @param newValue
94                  *            The new value of the option
95                  */
96                 public void optionChanged(Option<T> option, T oldValue, T newValue);
97
98         }
99
100         /**
101          * Basic implementation of an {@link Option} that notifies an
102          * {@link OptionWatcher} if the value changes.
103          *
104          * @param <T>
105          *            The type of the option
106          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
107          */
108         public static class DefaultOption<T> implements Option<T> {
109
110                 /** The default value. */
111                 private final T defaultValue;
112
113                 /** The current value. */
114                 private volatile T value;
115
116                 /** The option watcher. */
117                 private final List<OptionWatcher<T>> optionWatchers = new ArrayList<OptionWatcher<T>>();
118
119                 /**
120                  * Creates a new default option.
121                  *
122                  * @param defaultValue
123                  *            The default value of the option
124                  * @param optionWatchers
125                  *            The option watchers
126                  */
127                 public DefaultOption(T defaultValue, OptionWatcher<T>... optionWatchers) {
128                         this.defaultValue = defaultValue;
129                         this.optionWatchers.addAll(Arrays.asList(optionWatchers));
130                 }
131
132                 /**
133                  * {@inheritDoc}
134                  */
135                 @Override
136                 public T getDefault() {
137                         return defaultValue;
138                 }
139
140                 /**
141                  * {@inheritDoc}
142                  */
143                 @Override
144                 public T get() {
145                         return (value != null) ? value : defaultValue;
146                 }
147
148                 /**
149                  * Returns the real value of the option. This will also return an unset
150                  * value (usually {@code null})!
151                  *
152                  * @return The real value of the option
153                  */
154                 @Override
155                 public T getReal() {
156                         return value;
157                 }
158
159                 /**
160                  * {@inheritDoc}
161                  */
162                 @Override
163                 public void set(T value) {
164                         T oldValue = this.value;
165                         this.value = value;
166                         if (!get().equals(oldValue)) {
167                                 for (OptionWatcher<T> optionWatcher : optionWatchers) {
168                                         optionWatcher.optionChanged(this, oldValue, get());
169                                 }
170                         }
171                 }
172
173         }
174
175         /** Holds all {@link Boolean} {@link Option}s. */
176         private final Map<String, Option<Boolean>> booleanOptions = Collections.synchronizedMap(new HashMap<String, Option<Boolean>>());
177
178         /** Holds all {@link Integer} {@link Option}s. */
179         private final Map<String, Option<Integer>> integerOptions = Collections.synchronizedMap(new HashMap<String, Option<Integer>>());
180
181         /** Holds all {@link String} {@link Option}s. */
182         private final Map<String, Option<String>> stringOptions = Collections.synchronizedMap(new HashMap<String, Option<String>>());
183
184         /**
185          * Adds a boolean option.
186          *
187          * @param name
188          *            The name of the option
189          * @param booleanOption
190          *            The option
191          * @return The given option
192          */
193         public Option<Boolean> addBooleanOption(String name, Option<Boolean> booleanOption) {
194                 booleanOptions.put(name, booleanOption);
195                 return booleanOption;
196         }
197
198         /**
199          * Returns the boolean option with the given name.
200          *
201          * @param name
202          *            The name of the option
203          * @return The option, or {@code null} if there is no option with the given
204          *         name
205          */
206         public Option<Boolean> getBooleanOption(String name) {
207                 return booleanOptions.get(name);
208         }
209
210         /**
211          * Adds an {@link Integer} {@link Option}.
212          *
213          * @param name
214          *            The name of the option
215          * @param integerOption
216          *            The option
217          * @return The given option
218          */
219         public Option<Integer> addIntegerOption(String name, Option<Integer> integerOption) {
220                 integerOptions.put(name, integerOption);
221                 return integerOption;
222         }
223
224         /**
225          * Returns an {@link Integer} {@link Option}.
226          *
227          * @param name
228          *            The name of the integer option to get
229          * @return The integer option, or {@code null} if there is no option with
230          *         the given name
231          */
232         public Option<Integer> getIntegerOption(String name) {
233                 return integerOptions.get(name);
234         }
235
236         /**
237          * Adds a {@link String} {@link Option}.
238          *
239          * @param name
240          *            The name of the option
241          * @param stringOption
242          *            The option
243          * @return The given option
244          */
245         public Option<String> addStringOption(String name, Option<String> stringOption) {
246                 stringOptions.put(name, stringOption);
247                 return stringOption;
248         }
249
250         /**
251          * Returns a {@link String} {@link Option}.
252          *
253          * @param name
254          *            The name of the string option to get
255          * @return The string option, or {@code null} if there is no option with the
256          *         given name
257          */
258         public Option<String> getStringOption(String name) {
259                 return stringOptions.get(name);
260         }
261
262 }