|
@@ -23,6 +23,13 @@
|
23
|
23
|
package com.dmdirc.config;
|
24
|
24
|
|
25
|
25
|
import com.dmdirc.ui.messages.ColourManager;
|
|
26
|
+import com.dmdirc.util.validators.ColourValidator;
|
|
27
|
+import com.dmdirc.util.validators.DisabledOptionValidator;
|
|
28
|
+import com.dmdirc.util.validators.NumericalValidator;
|
|
29
|
+import com.dmdirc.util.validators.OptionalValidator;
|
|
30
|
+import com.dmdirc.util.validators.PermissiveValidator;
|
|
31
|
+import com.dmdirc.util.validators.Validator;
|
|
32
|
+import com.dmdirc.util.validators.ValidatorChain;
|
26
|
33
|
|
27
|
34
|
import java.awt.Color;
|
28
|
35
|
import java.util.ArrayList;
|
|
@@ -31,31 +38,82 @@ import java.util.List;
|
31
|
38
|
|
32
|
39
|
/**
|
33
|
40
|
* Defines methods to get options from a config source in various forms.
|
|
41
|
+ * <p>
|
|
42
|
+ * This implementation supports the idea of optional/disabled settings.
|
|
43
|
+ * This is where values may be prefixed with the strings <code>true:</code>
|
|
44
|
+ * or <code>false:</code>, where the former has no effect on the value of
|
|
45
|
+ * the setting, and the latter indicates that the user wishes to disable
|
|
46
|
+ * the setting.
|
|
47
|
+ * <p>
|
|
48
|
+ * Disabled settings allow for optional settings to have default values; a
|
|
49
|
+ * value can be added with the <code>false:</code> prefix which effectively
|
|
50
|
+ * disables the default value and makes the setting act as though it does not
|
|
51
|
+ * have a value. Note that for this sort of behaviour to make sense, it requires
|
|
52
|
+ * an implementation that takes values from multiple sources, such as a
|
|
53
|
+ * {@link ConfigManager}.
|
34
|
54
|
*
|
35
|
55
|
* @author chris
|
36
|
56
|
*/
|
37
|
57
|
public abstract class ConfigSource {
|
|
58
|
+
|
|
59
|
+ /** A permissive validator to use when callers don't specify one. */
|
|
60
|
+ private static final Validator<String> PERMISSIVE_VALIDATOR
|
|
61
|
+ = new PermissiveValidator<String>();
|
|
62
|
+
|
|
63
|
+ /** A validator for integer settings. */
|
|
64
|
+ private static final Validator<String> INT_VALIDATOR
|
|
65
|
+ = new OptionalValidator(new NumericalValidator(-1, -1));
|
|
66
|
+
|
|
67
|
+ /** A validator for colour settings. */
|
|
68
|
+ private static final Validator<String> COLOUR_VALIDATOR
|
|
69
|
+ = new OptionalValidator(new ColourValidator());
|
38
|
70
|
|
39
|
71
|
/**
|
40
|
|
- * Retrieves the specified option.
|
|
72
|
+ * Retrieves the specified option from this config source.
|
41
|
73
|
*
|
42
|
74
|
* @param domain The domain of the option
|
43
|
75
|
* @param option The name of the option
|
44
|
|
- * @return The value of the option
|
|
76
|
+ * @return The value of the option, or null if it doesn't exist
|
45
|
77
|
*/
|
46
|
|
- public abstract String getOption(final String domain, final String option);
|
|
78
|
+ public String getOption(final String domain, final String option) {
|
|
79
|
+ return getOption(domain, option, PERMISSIVE_VALIDATOR);
|
|
80
|
+ }
|
|
81
|
+
|
|
82
|
+ /**
|
|
83
|
+ * Retrieves the first value for the specified option that matches the
|
|
84
|
+ * specified validator.
|
|
85
|
+ *
|
|
86
|
+ * @since 0.6.5
|
|
87
|
+ * @param domain The domain of the option
|
|
88
|
+ * @param option The name of the option
|
|
89
|
+ * @param validator The validator to use to check legal values
|
|
90
|
+ * @return The value of the option, or null if no matching values exist
|
|
91
|
+ */
|
|
92
|
+ protected abstract String getOption(final String domain,
|
|
93
|
+ final String option, final Validator<String> validator);
|
47
|
94
|
|
48
|
95
|
/**
|
49
|
|
- * Determines if this manager has the specified option.
|
|
96
|
+ * Determines if this source has a value for the specified option which
|
|
97
|
+ * matches the specified validator.
|
50
|
98
|
*
|
|
99
|
+ * @since 0.6.5
|
51
|
100
|
* @param domain The domain of the option
|
52
|
101
|
* @param option The name of the option
|
53
|
|
- * @return True iff the option exists, false otherwise.
|
|
102
|
+ * @param validator The validator to use to check legal values
|
|
103
|
+ * @return True iff a matching option exists, false otherwise.
|
54
|
104
|
*/
|
55
|
|
- protected abstract boolean hasOption(final String domain, final String option);
|
|
105
|
+ protected abstract boolean hasOption(final String domain,
|
|
106
|
+ final String option, final Validator<String> validator);
|
56
|
107
|
|
57
|
108
|
/**
|
58
|
|
- * Determines if this manager has the specified String option.
|
|
109
|
+ * Determines if this source has the specified String option.
|
|
110
|
+ * <p>
|
|
111
|
+ * A String option is considered to exist if:
|
|
112
|
+ * <ul>
|
|
113
|
+ * <li>there is a value for the specified option,
|
|
114
|
+ * <li>that value is not empty, and
|
|
115
|
+ * <li>that value is not disabled (i.e., it doesn't begin with "false:")
|
|
116
|
+ * </ul>
|
59
|
117
|
*
|
60
|
118
|
* @param domain The domain of the option
|
61
|
119
|
* @param option The name of the option
|
|
@@ -63,14 +121,37 @@ public abstract class ConfigSource {
|
63
|
121
|
* @return True iff the option exists and is not empty, false otherwise
|
64
|
122
|
*/
|
65
|
123
|
public boolean hasOptionString(final String domain, final String option) {
|
|
124
|
+ return hasOptionString(domain, option, PERMISSIVE_VALIDATOR);
|
|
125
|
+ }
|
|
126
|
+
|
|
127
|
+ /**
|
|
128
|
+ * Determines if this source has the specified String option.
|
|
129
|
+ * <p>
|
|
130
|
+ * A String option is considered to exist if:
|
|
131
|
+ * <ul>
|
|
132
|
+ * <li>there is a value for the specified option that
|
|
133
|
+ * satisfies the specified validator,
|
|
134
|
+ * <li>that value is not empty, and
|
|
135
|
+ * <li>that value is not disabled (i.e., it doesn't begin with "false:")
|
|
136
|
+ * </ul>
|
|
137
|
+ *
|
|
138
|
+ * @param domain The domain of the option
|
|
139
|
+ * @param option The name of the option
|
|
140
|
+ * @param validator The validator to use to check legal values
|
|
141
|
+ * @since 0.6.5
|
|
142
|
+ * @return True iff the option exists and is not empty, false otherwise
|
|
143
|
+ */
|
|
144
|
+ public boolean hasOptionString(final String domain, final String option,
|
|
145
|
+ final Validator<String> validator) {
|
66
|
146
|
String value;
|
67
|
147
|
|
68
|
|
- return hasOption(domain, option) && !(value = getOption(domain, option)).isEmpty()
|
|
148
|
+ return hasOption(domain, option, validator)
|
|
149
|
+ && !(value = getOption(domain, option, validator)).isEmpty()
|
69
|
150
|
&& !value.startsWith("false:");
|
70
|
151
|
}
|
71
|
152
|
|
72
|
153
|
/**
|
73
|
|
- * Determines if this manager has the specified integer option.
|
|
154
|
+ * Determines if this source has the specified integer option.
|
74
|
155
|
*
|
75
|
156
|
* @param domain The domain of the option
|
76
|
157
|
* @param option The name of the option
|
|
@@ -79,19 +160,11 @@ public abstract class ConfigSource {
|
79
|
160
|
* false otherwise.
|
80
|
161
|
*/
|
81
|
162
|
public boolean hasOptionInt(final String domain, final String option) {
|
82
|
|
- if (hasOption(domain, option)) {
|
83
|
|
- try {
|
84
|
|
- return getOptionInt(domain, option) != null;
|
85
|
|
- } catch (NumberFormatException ex) {
|
86
|
|
- // Do nothing
|
87
|
|
- }
|
88
|
|
- }
|
89
|
|
-
|
90
|
|
- return false;
|
|
163
|
+ return hasOptionString(domain, option, INT_VALIDATOR);
|
91
|
164
|
}
|
92
|
165
|
|
93
|
166
|
/**
|
94
|
|
- * Determines if this manager has the specified character option.
|
|
167
|
+ * Determines if this source has the specified character option.
|
95
|
168
|
*
|
96
|
169
|
* @param domain The domain of the option
|
97
|
170
|
* @param option The name of the option
|
|
@@ -100,11 +173,11 @@ public abstract class ConfigSource {
|
100
|
173
|
* false otherwise.
|
101
|
174
|
*/
|
102
|
175
|
public boolean hasOptionChar(final String domain, final String option) {
|
103
|
|
- return hasOption(domain, option) && !getOption(domain, option).isEmpty();
|
|
176
|
+ return hasOptionString(domain, option);
|
104
|
177
|
}
|
105
|
178
|
|
106
|
179
|
/**
|
107
|
|
- * Determines if this manager has the specified colour option.
|
|
180
|
+ * Determines if this source has the specified colour option.
|
108
|
181
|
*
|
109
|
182
|
* @param domain The domain of the option
|
110
|
183
|
* @param option The name of the option
|
|
@@ -113,20 +186,7 @@ public abstract class ConfigSource {
|
113
|
186
|
* false otherwise.
|
114
|
187
|
*/
|
115
|
188
|
public boolean hasOptionColour(final String domain, final String option) {
|
116
|
|
- if (hasOption(domain, option)) {
|
117
|
|
- String value = getOption(domain, option);
|
118
|
|
- String colour;
|
119
|
|
-
|
120
|
|
- if (value.startsWith("true:")) {
|
121
|
|
- colour = value.substring(5);
|
122
|
|
- } else {
|
123
|
|
- colour = value;
|
124
|
|
- }
|
125
|
|
-
|
126
|
|
- return ColourManager.parseColour(colour, null) != null;
|
127
|
|
- } else {
|
128
|
|
- return false;
|
129
|
|
- }
|
|
189
|
+ return hasOptionString(domain, option, COLOUR_VALIDATOR);
|
130
|
190
|
}
|
131
|
191
|
|
132
|
192
|
/**
|
|
@@ -137,27 +197,44 @@ public abstract class ConfigSource {
|
137
|
197
|
* @return The boolean representation of the option
|
138
|
198
|
*/
|
139
|
199
|
public boolean hasOptionBool(final String domain, final String option) {
|
140
|
|
- return hasOption(domain, option);
|
|
200
|
+ return hasOption(domain, option, PERMISSIVE_VALIDATOR);
|
141
|
201
|
}
|
142
|
|
-
|
|
202
|
+
|
143
|
203
|
/**
|
144
|
|
- * Retrieves the specified option as a String, if it exists
|
|
204
|
+ * Retrieves the specified option as a String, if it exists and satisfies
|
|
205
|
+ * the specified validator.
|
|
206
|
+ * <p>
|
|
207
|
+ * If no fallback settings are supplied (or if fallback settings are
|
|
208
|
+ * supplied and execution reaches the last fallback setting) AND if the
|
|
209
|
+ * 'required' parameter is true, then all disabled values (i.e., those
|
|
210
|
+ * starting with <code>false:</code>) will be ignored. To check if a valid
|
|
211
|
+ * non-disabled value exists, call
|
|
212
|
+ * {@link #hasOptionString(java.lang.String, java.lang.String, com.dmdirc.util.validators.Validator)}.
|
145
|
213
|
*
|
146
|
214
|
* @param domain The domain of the option
|
147
|
215
|
* @param option The name of the option
|
|
216
|
+ * @param required Whether the specified option is required or not
|
|
217
|
+ * @param validator The validator to use to check the value
|
148
|
218
|
* @param fallbacks An ordered array of further domains and options
|
149
|
219
|
* (in pairs) to try if the specified domain/option isn't found
|
150
|
220
|
* @return The string representation of the option or null if optional
|
151
|
221
|
* setting is not specified
|
152
|
|
- * @since 0.6.3
|
|
222
|
+ * @since 0.6.5
|
153
|
223
|
*/
|
154
|
224
|
public String getOptionString(final String domain, final String option,
|
|
225
|
+ final boolean required, final Validator<String> validator,
|
155
|
226
|
final String ... fallbacks) {
|
156
|
227
|
String value;
|
|
228
|
+
|
|
229
|
+ @SuppressWarnings("unchecked")
|
|
230
|
+ final Validator<String> newValidator = required && fallbacks.length == 0
|
|
231
|
+ ? new ValidatorChain<String>(new DisabledOptionValidator(), validator)
|
|
232
|
+ : validator;
|
157
|
233
|
|
158
|
|
- if (!hasOption(domain, option) || (value = getOption(domain, option))
|
159
|
|
- .startsWith("false:")) {
|
160
|
|
- return fallbacks.length >= 2 ? getOptionString(fallbacks[0], fallbacks[1],
|
|
234
|
+ if (!hasOption(domain, option, newValidator)
|
|
235
|
+ || (value = getOption(domain, option, newValidator)).startsWith("false:")) {
|
|
236
|
+ return fallbacks.length >= 2 ? getOptionString(fallbacks[0],
|
|
237
|
+ fallbacks[1], required, validator,
|
161
|
238
|
Arrays.copyOfRange(fallbacks, 2, fallbacks.length)) : null;
|
162
|
239
|
} else if (value.startsWith("true:")) {
|
163
|
240
|
return value.substring(5);
|
|
@@ -166,6 +243,22 @@ public abstract class ConfigSource {
|
166
|
243
|
}
|
167
|
244
|
}
|
168
|
245
|
|
|
246
|
+ /**
|
|
247
|
+ * Retrieves the specified option as a String, if it exists.
|
|
248
|
+ *
|
|
249
|
+ * @param domain The domain of the option
|
|
250
|
+ * @param option The name of the option
|
|
251
|
+ * @param fallbacks An ordered array of further domains and options
|
|
252
|
+ * (in pairs) to try if the specified domain/option isn't found
|
|
253
|
+ * @return The string representation of the option or null if optional
|
|
254
|
+ * setting is not specified
|
|
255
|
+ * @since 0.6.3
|
|
256
|
+ */
|
|
257
|
+ public String getOptionString(final String domain, final String option,
|
|
258
|
+ final String ... fallbacks) {
|
|
259
|
+ return getOptionString(domain, option, true, PERMISSIVE_VALIDATOR, fallbacks);
|
|
260
|
+ }
|
|
261
|
+
|
169
|
262
|
/**
|
170
|
263
|
* Retrieves the specified option as a character.
|
171
|
264
|
*
|
|
@@ -189,7 +282,7 @@ public abstract class ConfigSource {
|
189
|
282
|
*/
|
190
|
283
|
public Color getOptionColour(final String domain, final String option,
|
191
|
284
|
final String ... fallbacks) {
|
192
|
|
- final String value = getOptionString(domain, option, fallbacks);
|
|
285
|
+ final String value = getOptionString(domain, option, true, COLOUR_VALIDATOR, fallbacks);
|
193
|
286
|
|
194
|
287
|
return value == null ? null : ColourManager.parseColour(value, null);
|
195
|
288
|
}
|
|
@@ -217,7 +310,7 @@ public abstract class ConfigSource {
|
217
|
310
|
final boolean trimEmpty) {
|
218
|
311
|
final List<String> res = new ArrayList<String>();
|
219
|
312
|
|
220
|
|
- if (hasOption(domain, option)) {
|
|
313
|
+ if (hasOption(domain, option, PERMISSIVE_VALIDATOR)) {
|
221
|
314
|
for (String line : getOption(domain, option).split("\n")) {
|
222
|
315
|
if (!line.isEmpty() || !trimEmpty) {
|
223
|
316
|
res.add(line);
|
|
@@ -239,7 +332,7 @@ public abstract class ConfigSource {
|
239
|
332
|
public List<String> getOptionList(final String domain, final String option) {
|
240
|
333
|
return getOptionList(domain, option, true);
|
241
|
334
|
}
|
242
|
|
-
|
|
335
|
+
|
243
|
336
|
/**
|
244
|
337
|
* Retrieves an integral representation of the specified option.
|
245
|
338
|
*
|
|
@@ -247,13 +340,27 @@ public abstract class ConfigSource {
|
247
|
340
|
* @param option The name of the option
|
248
|
341
|
* @param fallbacks An ordered array of further domains and options
|
249
|
342
|
* (in pairs) to try if the specified domain/option isn't found
|
250
|
|
- * @throws NumberFormatException If the setting can't be parsed
|
251
|
|
- * @return The integer representation of the option or null if optional
|
252
|
|
- * setting is false
|
|
343
|
+ * @return The integer representation of the option
|
253
|
344
|
*/
|
254
|
345
|
public Integer getOptionInt(final String domain, final String option,
|
255
|
346
|
final String ... fallbacks) {
|
256
|
|
- final String value = getOptionString(domain, option, fallbacks);
|
|
347
|
+ return getOptionInt(domain, option, true, fallbacks);
|
|
348
|
+ }
|
|
349
|
+
|
|
350
|
+ /**
|
|
351
|
+ * Retrieves an integral representation of the specified option.
|
|
352
|
+ *
|
|
353
|
+ * @since 0.6.5
|
|
354
|
+ * @param domain The domain of the option
|
|
355
|
+ * @param option The name of the option
|
|
356
|
+ * @param required Whether this option is required or optional
|
|
357
|
+ * @param fallbacks An ordered array of further domains and options
|
|
358
|
+ * (in pairs) to try if the specified domain/option isn't found
|
|
359
|
+ * @return The integer representation of the option
|
|
360
|
+ */
|
|
361
|
+ public Integer getOptionInt(final String domain, final String option,
|
|
362
|
+ final boolean required, final String ... fallbacks) {
|
|
363
|
+ final String value = getOptionString(domain, option, required, INT_VALIDATOR, fallbacks);
|
257
|
364
|
|
258
|
365
|
return value == null ? null : Integer.parseInt(value.trim());
|
259
|
366
|
}
|