Make the option watcher optional.
[Sone.git] / src / main / java / net / pterodactylus / sone / core / Options.java
1 package net.pterodactylus.sone.core;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8
9 /**
10  * Stores various options that influence Sone’s behaviour.
11  *
12  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
13  */
14 public class Options {
15
16         /**
17          * Contains current and default value of an option.
18          *
19          * @param <T>
20          *            The type of the option
21          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
22          */
23         public static interface Option<T> {
24
25                 /**
26                  * Returns the default value of the option.
27                  *
28                  * @return The default value of the option
29                  */
30                 public T getDefault();
31
32                 /**
33                  * Returns the current value of the option. If the current value is not
34                  * set (usually {@code null}), the default value is returned.
35                  *
36                  * @return The current value of the option
37                  */
38                 public T get();
39
40                 /**
41                  * Returns the real value of the option. This will also return an unset
42                  * value (usually {@code null})!
43                  *
44                  * @return The real value of the option
45                  */
46                 public T getReal();
47
48                 /**
49                  * Sets the current value of the option.
50                  *
51                  * @param value
52                  *            The new value of the option
53                  */
54                 public void set(T value);
55
56         }
57
58         /**
59          * Interface for objects that want to be notified when an option changes its
60          * value.
61          *
62          * @param <T>
63          *            The type of the option
64          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
65          */
66         public static interface OptionWatcher<T> {
67
68                 /**
69                  * Notifies an object that an option has been changed.
70                  *
71                  * @param option
72                  *            The option that has changed
73                  * @param oldValue
74                  *            The old value of the option
75                  * @param newValue
76                  *            The new value of the option
77                  */
78                 public void optionChanged(Option<T> option, T oldValue, T newValue);
79
80         }
81
82         /**
83          * Basic implementation of an {@link Option} that notifies an
84          * {@link OptionWatcher} if the value changes.
85          *
86          * @param <T>
87          *            The type of the option
88          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
89          */
90         public static class DefaultOption<T> implements Option<T> {
91
92                 /** The default value. */
93                 private final T defaultValue;
94
95                 /** The current value. */
96                 private T value;
97
98                 /** The option watcher. */
99                 private final List<OptionWatcher<T>> optionWatchers = new ArrayList<OptionWatcher<T>>();
100
101                 /**
102                  * Creates a new default option.
103                  *
104                  * @param defaultValue
105                  *            The default value of the option
106                  * @param optionWatchers
107                  *            The option watchers
108                  */
109                 public DefaultOption(T defaultValue, OptionWatcher<T>... optionWatchers) {
110                         this.defaultValue = defaultValue;
111                         this.optionWatchers.addAll(Arrays.asList(optionWatchers));
112                 }
113
114                 /**
115                  * {@inheritDoc}
116                  */
117                 @Override
118                 public T getDefault() {
119                         return defaultValue;
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 void set(T value) {
146                         T oldValue = this.value;
147                         this.value = value;
148                         if (!get().equals(oldValue)) {
149                                 for (OptionWatcher<T> optionWatcher : optionWatchers) {
150                                         optionWatcher.optionChanged(this, oldValue, get());
151                                 }
152                         }
153                 }
154
155         }
156
157         /** Holds all {@link Integer} {@link Option}s. */
158         private final Map<String, Option<Integer>> integerOptions = new HashMap<String, Option<Integer>>();
159
160         /**
161          * Adds an {@link Integer} {@link Option}.
162          *
163          * @param name
164          *            The name of the option
165          * @param integerOption
166          *            The option
167          * @return The given option
168          */
169         public Option<Integer> addIntegerOption(String name, Option<Integer> integerOption) {
170                 integerOptions.put(name, integerOption);
171                 return integerOption;
172         }
173
174         /**
175          * Returns an {@link Integer} {@link Option}.
176          *
177          * @param name
178          *            The name of the integer option to get
179          * @return The integer option, or {@code null} if there is no option with
180          *         the given name
181          */
182         public Option<Integer> getIntegerOption(String name) {
183                 return integerOptions.get(name);
184         }
185
186 }