Commit | Line | Data |
---|---|---|
ec1f3444 NR |
1 | package be.nikiroo.utils.resources; |
2 | ||
3 | import java.io.BufferedWriter; | |
4 | import java.io.File; | |
5 | import java.io.FileInputStream; | |
6 | import java.io.FileOutputStream; | |
7 | import java.io.IOException; | |
712ddafb | 8 | import java.io.InputStream; |
ec1f3444 NR |
9 | import java.io.InputStreamReader; |
10 | import java.io.OutputStreamWriter; | |
11 | import java.io.Reader; | |
ec1f3444 NR |
12 | import java.io.Writer; |
13 | import java.lang.reflect.Field; | |
14 | import java.util.ArrayList; | |
62c9ec78 | 15 | import java.util.HashMap; |
ec1f3444 NR |
16 | import java.util.List; |
17 | import java.util.Locale; | |
62c9ec78 | 18 | import java.util.Map; |
ec1f3444 NR |
19 | import java.util.MissingResourceException; |
20 | import java.util.PropertyResourceBundle; | |
21 | import java.util.ResourceBundle; | |
22 | ||
b15a4985 NR |
23 | import be.nikiroo.utils.resources.Meta.Format; |
24 | ||
ec1f3444 | 25 | /** |
62c9ec78 | 26 | * This class encapsulate a {@link ResourceBundle} in UTF-8. It allows to |
ec1f3444 NR |
27 | * retrieve values associated to an enumeration, and allows some additional |
28 | * methods. | |
62c9ec78 NR |
29 | * <p> |
30 | * It also sports a writable change map, and you can save back the | |
31 | * {@link Bundle} to file with {@link Bundle#updateFile(String)}. | |
ec1f3444 | 32 | * |
ec1f3444 NR |
33 | * @param <E> |
34 | * the enum to use to get values out of this class | |
db31c358 NR |
35 | * |
36 | * @author niki | |
ec1f3444 | 37 | */ |
db31c358 | 38 | |
ec1f3444 | 39 | public class Bundle<E extends Enum<E>> { |
db31c358 | 40 | /** The type of E. */ |
ec1f3444 | 41 | protected Class<E> type; |
db31c358 NR |
42 | /** |
43 | * The {@link Enum} associated to this {@link Bundle} (all the keys used in | |
44 | * this {@link Bundle} will be of this type). | |
45 | */ | |
46 | protected Enum<?> keyType; | |
47 | ||
48 | private TransBundle<E> descriptionBundle; | |
49 | ||
50 | /** R/O map */ | |
51 | private Map<String, String> map; | |
52 | /** R/W map */ | |
53 | private Map<String, String> changeMap; | |
ec1f3444 NR |
54 | |
55 | /** | |
56 | * Create a new {@link Bundles} of the given name. | |
57 | * | |
58 | * @param type | |
59 | * a runtime instance of the class of E | |
ec1f3444 NR |
60 | * @param name |
61 | * the name of the {@link Bundles} | |
db31c358 NR |
62 | * @param descriptionBundle |
63 | * the description {@link TransBundle}, that is, a | |
64 | * {@link TransBundle} dedicated to the description of the values | |
65 | * of the given {@link Bundle} (can be NULL) | |
ec1f3444 | 66 | */ |
db31c358 NR |
67 | protected Bundle(Class<E> type, Enum<?> name, |
68 | TransBundle<E> descriptionBundle) { | |
ec1f3444 | 69 | this.type = type; |
db31c358 NR |
70 | this.keyType = name; |
71 | this.descriptionBundle = descriptionBundle; | |
72 | ||
487926f7 | 73 | this.map = new HashMap<String, String>(); |
62c9ec78 | 74 | this.changeMap = new HashMap<String, String>(); |
e9ca6bb8 | 75 | setBundle(name, Locale.getDefault(), false); |
ec1f3444 NR |
76 | } |
77 | ||
13bfeea6 NR |
78 | /** |
79 | * Check if the setting is set into this {@link Bundle}. | |
80 | * | |
81 | * @param id | |
82 | * the id of the setting to check | |
83 | * @param includeDefaultValue | |
84 | * TRUE to only return false when the setting is not set AND | |
85 | * there is no default value | |
86 | * | |
87 | * @return TRUE if the setting is set | |
88 | */ | |
b15a4985 NR |
89 | public boolean isSet(E id, boolean includeDefaultValue) { |
90 | return isSet(id.name(), includeDefaultValue); | |
91 | } | |
92 | ||
93 | /** | |
94 | * Check if the setting is set into this {@link Bundle}. | |
95 | * | |
856f5898 | 96 | * @param name |
b15a4985 NR |
97 | * the id of the setting to check |
98 | * @param includeDefaultValue | |
06359ad5 NR |
99 | * TRUE to only return false when the setting is explicitly set |
100 | * to NULL (and not just "no set") in the change maps | |
b15a4985 NR |
101 | * |
102 | * @return TRUE if the setting is set | |
103 | */ | |
104 | protected boolean isSet(String name, boolean includeDefaultValue) { | |
105 | if (getString(name, null) == null) { | |
106 | if (!includeDefaultValue || getString(name, "") == null) { | |
13bfeea6 NR |
107 | return false; |
108 | } | |
109 | } | |
110 | ||
111 | return true; | |
112 | } | |
113 | ||
ec1f3444 NR |
114 | /** |
115 | * Return the value associated to the given id as a {@link String}. | |
116 | * | |
db31c358 | 117 | * @param id |
ec1f3444 NR |
118 | * the id of the value to get |
119 | * | |
120 | * @return the associated value, or NULL if not found (not present in the | |
121 | * resource file) | |
122 | */ | |
123 | public String getString(E id) { | |
13bfeea6 NR |
124 | return getString(id, null); |
125 | } | |
126 | ||
127 | /** | |
128 | * Return the value associated to the given id as a {@link String}. | |
129 | * <p> | |
130 | * If no value is associated, take the default one if any. | |
131 | * | |
132 | * @param id | |
133 | * the id of the value to get | |
134 | * @param def | |
135 | * the default value when it is not present in the config file | |
136 | * | |
b9839223 NR |
137 | * @return the associated value, or <tt>def</tt> if not found (not present |
138 | * in the resource file) | |
13bfeea6 NR |
139 | */ |
140 | public String getString(E id, String def) { | |
d5026c09 NR |
141 | return getString(id, def, -1); |
142 | } | |
143 | ||
144 | /** | |
145 | * Return the value associated to the given id as a {@link String}. | |
146 | * <p> | |
24604392 NR |
147 | * If no value is associated (or if it is empty!), take the default one if |
148 | * any. | |
d5026c09 NR |
149 | * |
150 | * @param id | |
151 | * the id of the value to get | |
152 | * @param def | |
153 | * the default value when it is not present in the config file | |
154 | * @param item | |
155 | * the item number to get for an array of values, or -1 for | |
156 | * non-arrays | |
157 | * | |
b9839223 NR |
158 | * @return the associated value, <tt>def</tt> if not found (not present in |
159 | * the resource file) or NULL if the item is specified (not -1) and | |
160 | * does not exist | |
d5026c09 NR |
161 | */ |
162 | public String getString(E id, String def, int item) { | |
13bfeea6 NR |
163 | String rep = getString(id.name(), null); |
164 | if (rep == null) { | |
06359ad5 | 165 | rep = getMetaDef(id.name()); |
13bfeea6 NR |
166 | } |
167 | ||
b9839223 | 168 | if (rep.isEmpty()) { |
d5026c09 NR |
169 | return def; |
170 | } | |
171 | ||
172 | if (item >= 0) { | |
173 | List<String> values = BundleHelper.parseList(rep, item); | |
174 | if (values != null && item < values.size()) { | |
175 | return values.get(item); | |
176 | } | |
177 | ||
178 | return null; | |
13bfeea6 NR |
179 | } |
180 | ||
181 | return rep; | |
ec1f3444 NR |
182 | } |
183 | ||
62c9ec78 NR |
184 | /** |
185 | * Set the value associated to the given id as a {@link String}. | |
186 | * | |
db31c358 | 187 | * @param id |
3bfc1d20 | 188 | * the id of the value to set |
62c9ec78 NR |
189 | * @param value |
190 | * the value | |
191 | * | |
192 | */ | |
193 | public void setString(E id, String value) { | |
487926f7 | 194 | setString(id.name(), value); |
62c9ec78 NR |
195 | } |
196 | ||
d5026c09 NR |
197 | /** |
198 | * Set the value associated to the given id as a {@link String}. | |
199 | * | |
200 | * @param id | |
201 | * the id of the value to set | |
202 | * @param value | |
203 | * the value | |
204 | * @param item | |
205 | * the item number to get for an array of values, or -1 for | |
206 | * non-arrays | |
207 | * | |
208 | */ | |
209 | public void setString(E id, String value, int item) { | |
210 | if (item < 0) { | |
211 | setString(id.name(), value); | |
212 | } else { | |
213 | List<String> values = getList(id); | |
856f5898 | 214 | setString(id.name(), BundleHelper.fromList(values, value, item)); |
d5026c09 NR |
215 | } |
216 | } | |
217 | ||
ec1f3444 NR |
218 | /** |
219 | * Return the value associated to the given id as a {@link String} suffixed | |
220 | * with the runtime value "_suffix" (that is, "_" and suffix). | |
487926f7 NR |
221 | * <p> |
222 | * Will only accept suffixes that form an existing id. | |
13bfeea6 NR |
223 | * <p> |
224 | * If no value is associated, take the default one if any. | |
ec1f3444 | 225 | * |
db31c358 | 226 | * @param id |
ec1f3444 NR |
227 | * the id of the value to get |
228 | * @param suffix | |
229 | * the runtime suffix | |
230 | * | |
231 | * @return the associated value, or NULL if not found (not present in the | |
232 | * resource file) | |
233 | */ | |
234 | public String getStringX(E id, String suffix) { | |
d5026c09 NR |
235 | return getStringX(id, suffix, null, -1); |
236 | } | |
237 | ||
238 | /** | |
239 | * Return the value associated to the given id as a {@link String} suffixed | |
240 | * with the runtime value "_suffix" (that is, "_" and suffix). | |
241 | * <p> | |
242 | * Will only accept suffixes that form an existing id. | |
243 | * <p> | |
244 | * If no value is associated, take the default one if any. | |
245 | * | |
246 | * @param id | |
247 | * the id of the value to get | |
248 | * @param suffix | |
249 | * the runtime suffix | |
250 | * @param def | |
251 | * the default value when it is not present in the config file | |
252 | * | |
253 | * @return the associated value, or NULL if not found (not present in the | |
254 | * resource file) | |
255 | */ | |
256 | public String getStringX(E id, String suffix, String def) { | |
257 | return getStringX(id, suffix, def, -1); | |
258 | } | |
259 | ||
260 | /** | |
261 | * Return the value associated to the given id as a {@link String} suffixed | |
262 | * with the runtime value "_suffix" (that is, "_" and suffix). | |
263 | * <p> | |
264 | * Will only accept suffixes that form an existing id. | |
265 | * <p> | |
266 | * If no value is associated, take the default one if any. | |
267 | * | |
268 | * @param id | |
269 | * the id of the value to get | |
270 | * @param suffix | |
271 | * the runtime suffix | |
d5026c09 NR |
272 | * @param def |
273 | * the default value when it is not present in the config file | |
274 | * @param item | |
275 | * the item number to get for an array of values, or -1 for | |
276 | * non-arrays | |
277 | * | |
b9839223 NR |
278 | * @return the associated value, <tt>def</tt> if not found (not present in |
279 | * the resource file), NULL if the item is specified (not -1) but | |
280 | * does not exist and NULL if bad key | |
d5026c09 NR |
281 | */ |
282 | public String getStringX(E id, String suffix, String def, int item) { | |
ec1f3444 | 283 | String key = id.name() |
80383c14 | 284 | + (suffix == null ? "" : "_" + suffix.toUpperCase()); |
ec1f3444 | 285 | |
487926f7 NR |
286 | try { |
287 | id = Enum.valueOf(type, key); | |
d5026c09 | 288 | return getString(id, def, item); |
487926f7 | 289 | } catch (IllegalArgumentException e) { |
ec1f3444 NR |
290 | } |
291 | ||
292 | return null; | |
293 | } | |
294 | ||
62c9ec78 NR |
295 | /** |
296 | * Set the value associated to the given id as a {@link String} suffixed | |
297 | * with the runtime value "_suffix" (that is, "_" and suffix). | |
487926f7 NR |
298 | * <p> |
299 | * Will only accept suffixes that form an existing id. | |
62c9ec78 | 300 | * |
db31c358 | 301 | * @param id |
3bfc1d20 | 302 | * the id of the value to set |
62c9ec78 NR |
303 | * @param suffix |
304 | * the runtime suffix | |
305 | * @param value | |
306 | * the value | |
307 | */ | |
308 | public void setStringX(E id, String suffix, String value) { | |
d5026c09 NR |
309 | setStringX(id, suffix, value, -1); |
310 | } | |
311 | ||
312 | /** | |
313 | * Set the value associated to the given id as a {@link String} suffixed | |
314 | * with the runtime value "_suffix" (that is, "_" and suffix). | |
315 | * <p> | |
316 | * Will only accept suffixes that form an existing id. | |
317 | * | |
318 | * @param id | |
319 | * the id of the value to set | |
320 | * @param suffix | |
321 | * the runtime suffix | |
322 | * @param value | |
323 | * the value | |
324 | * @param item | |
325 | * the item number to get for an array of values, or -1 for | |
326 | * non-arrays | |
327 | */ | |
328 | public void setStringX(E id, String suffix, String value, int item) { | |
62c9ec78 NR |
329 | String key = id.name() |
330 | + (suffix == null ? "" : "_" + suffix.toUpperCase()); | |
331 | ||
487926f7 NR |
332 | try { |
333 | id = Enum.valueOf(type, key); | |
d5026c09 | 334 | setString(id, value, item); |
487926f7 | 335 | } catch (IllegalArgumentException e) { |
487926f7 | 336 | } |
62c9ec78 NR |
337 | } |
338 | ||
ec1f3444 NR |
339 | /** |
340 | * Return the value associated to the given id as a {@link Boolean}. | |
13bfeea6 NR |
341 | * <p> |
342 | * If no value is associated, take the default one if any. | |
ec1f3444 | 343 | * |
db31c358 | 344 | * @param id |
ec1f3444 NR |
345 | * the id of the value to get |
346 | * | |
347 | * @return the associated value | |
348 | */ | |
349 | public Boolean getBoolean(E id) { | |
d5026c09 | 350 | return BundleHelper.parseBoolean(getString(id), -1); |
ec1f3444 NR |
351 | } |
352 | ||
353 | /** | |
62c9ec78 | 354 | * Return the value associated to the given id as a {@link Boolean}. |
13bfeea6 NR |
355 | * <p> |
356 | * If no value is associated, take the default one if any. | |
ec1f3444 | 357 | * |
db31c358 | 358 | * @param id |
ec1f3444 NR |
359 | * the id of the value to get |
360 | * @param def | |
361 | * the default value when it is not present in the config file or | |
362 | * if it is not a boolean value | |
363 | * | |
364 | * @return the associated value | |
365 | */ | |
366 | public boolean getBoolean(E id, boolean def) { | |
d5026c09 NR |
367 | Boolean value = getBoolean(id); |
368 | if (value != null) { | |
369 | return value; | |
370 | } | |
371 | ||
372 | return def; | |
373 | } | |
374 | ||
375 | /** | |
376 | * Return the value associated to the given id as a {@link Boolean}. | |
377 | * <p> | |
378 | * If no value is associated, take the default one if any. | |
379 | * | |
380 | * @param id | |
381 | * the id of the value to get | |
382 | * @param def | |
383 | * the default value when it is not present in the config file or | |
384 | * if it is not a boolean value | |
385 | * @param item | |
386 | * the item number to get for an array of values, or -1 for | |
387 | * non-arrays | |
388 | * | |
389 | * @return the associated value | |
390 | */ | |
391 | public Boolean getBoolean(E id, boolean def, int item) { | |
392 | String value = getString(id); | |
393 | if (value != null) { | |
394 | return BundleHelper.parseBoolean(value, item); | |
395 | } | |
ec1f3444 NR |
396 | |
397 | return def; | |
398 | } | |
d18e136e | 399 | |
3bfc1d20 NR |
400 | /** |
401 | * Set the value associated to the given id as a {@link Boolean}. | |
402 | * | |
403 | * @param id | |
404 | * the id of the value to set | |
405 | * @param value | |
406 | * the value | |
407 | * | |
408 | */ | |
409 | public void setBoolean(E id, boolean value) { | |
d5026c09 NR |
410 | setBoolean(id, value, -1); |
411 | } | |
412 | ||
413 | /** | |
414 | * Set the value associated to the given id as a {@link Boolean}. | |
415 | * | |
416 | * @param id | |
417 | * the id of the value to set | |
418 | * @param value | |
419 | * the value | |
420 | * @param item | |
421 | * the item number to get for an array of values, or -1 for | |
422 | * non-arrays | |
423 | * | |
424 | */ | |
425 | public void setBoolean(E id, boolean value, int item) { | |
426 | setString(id, BundleHelper.fromBoolean(value), item); | |
3bfc1d20 NR |
427 | } |
428 | ||
ec1f3444 NR |
429 | /** |
430 | * Return the value associated to the given id as an {@link Integer}. | |
13bfeea6 NR |
431 | * <p> |
432 | * If no value is associated, take the default one if any. | |
ec1f3444 | 433 | * |
db31c358 | 434 | * @param id |
ec1f3444 NR |
435 | * the id of the value to get |
436 | * | |
437 | * @return the associated value | |
438 | */ | |
439 | public Integer getInteger(E id) { | |
d5026c09 NR |
440 | String value = getString(id); |
441 | if (value != null) { | |
442 | return BundleHelper.parseInteger(value, -1); | |
443 | } | |
444 | ||
445 | return null; | |
ec1f3444 NR |
446 | } |
447 | ||
448 | /** | |
db31c358 | 449 | * Return the value associated to the given id as an int. |
13bfeea6 NR |
450 | * <p> |
451 | * If no value is associated, take the default one if any. | |
ec1f3444 | 452 | * |
db31c358 | 453 | * @param id |
ec1f3444 NR |
454 | * the id of the value to get |
455 | * @param def | |
456 | * the default value when it is not present in the config file or | |
457 | * if it is not a int value | |
458 | * | |
459 | * @return the associated value | |
460 | */ | |
461 | public int getInteger(E id, int def) { | |
d5026c09 NR |
462 | Integer value = getInteger(id); |
463 | if (value != null) { | |
464 | return value; | |
465 | } | |
466 | ||
467 | return def; | |
468 | } | |
469 | ||
470 | /** | |
471 | * Return the value associated to the given id as an int. | |
472 | * <p> | |
473 | * If no value is associated, take the default one if any. | |
474 | * | |
475 | * @param id | |
476 | * the id of the value to get | |
477 | * @param def | |
478 | * the default value when it is not present in the config file or | |
479 | * if it is not a int value | |
480 | * @param item | |
481 | * the item number to get for an array of values, or -1 for | |
482 | * non-arrays | |
483 | * | |
484 | * @return the associated value | |
485 | */ | |
486 | public Integer getInteger(E id, int def, int item) { | |
487 | String value = getString(id); | |
488 | if (value != null) { | |
489 | return BundleHelper.parseInteger(value, item); | |
490 | } | |
ec1f3444 NR |
491 | |
492 | return def; | |
493 | } | |
494 | ||
3bfc1d20 NR |
495 | /** |
496 | * Set the value associated to the given id as a {@link Integer}. | |
497 | * | |
498 | * @param id | |
499 | * the id of the value to set | |
500 | * @param value | |
501 | * the value | |
502 | * | |
503 | */ | |
504 | public void setInteger(E id, int value) { | |
d5026c09 NR |
505 | setInteger(id, value, -1); |
506 | } | |
507 | ||
508 | /** | |
509 | * Set the value associated to the given id as a {@link Integer}. | |
510 | * | |
511 | * @param id | |
512 | * the id of the value to set | |
513 | * @param value | |
514 | * the value | |
515 | * @param item | |
516 | * the item number to get for an array of values, or -1 for | |
517 | * non-arrays | |
518 | * | |
519 | */ | |
520 | public void setInteger(E id, int value, int item) { | |
521 | setString(id, BundleHelper.fromInteger(value), item); | |
3bfc1d20 | 522 | } |
d18e136e | 523 | |
ec1f3444 NR |
524 | /** |
525 | * Return the value associated to the given id as a {@link Character}. | |
13bfeea6 NR |
526 | * <p> |
527 | * If no value is associated, take the default one if any. | |
ec1f3444 | 528 | * |
db31c358 | 529 | * @param id |
ec1f3444 NR |
530 | * the id of the value to get |
531 | * | |
532 | * @return the associated value | |
533 | */ | |
62c9ec78 | 534 | public Character getCharacter(E id) { |
d5026c09 | 535 | return BundleHelper.parseCharacter(getString(id), -1); |
62c9ec78 NR |
536 | } |
537 | ||
538 | /** | |
539 | * Return the value associated to the given id as a {@link Character}. | |
13bfeea6 NR |
540 | * <p> |
541 | * If no value is associated, take the default one if any. | |
62c9ec78 | 542 | * |
db31c358 | 543 | * @param id |
62c9ec78 NR |
544 | * the id of the value to get |
545 | * @param def | |
546 | * the default value when it is not present in the config file or | |
547 | * if it is not a char value | |
548 | * | |
549 | * @return the associated value | |
550 | */ | |
551 | public char getCharacter(E id, char def) { | |
d5026c09 NR |
552 | Character value = getCharacter(id); |
553 | if (value != null) { | |
554 | return value; | |
555 | } | |
556 | ||
557 | return def; | |
558 | } | |
559 | ||
560 | /** | |
561 | * Return the value associated to the given id as a {@link Character}. | |
562 | * <p> | |
563 | * If no value is associated, take the default one if any. | |
564 | * | |
565 | * @param id | |
566 | * the id of the value to get | |
567 | * @param def | |
568 | * the default value when it is not present in the config file or | |
569 | * if it is not a char value | |
856f5898 NR |
570 | * @param item |
571 | * the item number to get for an array of values, or -1 for | |
572 | * non-arrays | |
d5026c09 NR |
573 | * |
574 | * @return the associated value | |
575 | */ | |
576 | public Character getCharacter(E id, char def, int item) { | |
577 | String value = getString(id); | |
578 | if (value != null) { | |
579 | return BundleHelper.parseCharacter(value, item); | |
580 | } | |
62c9ec78 NR |
581 | |
582 | return def; | |
ec1f3444 NR |
583 | } |
584 | ||
d5026c09 NR |
585 | /** |
586 | * Set the value associated to the given id as a {@link Character}. | |
587 | * | |
588 | * @param id | |
589 | * the id of the value to set | |
590 | * @param value | |
591 | * the value | |
592 | * | |
593 | */ | |
594 | public void setCharacter(E id, char value) { | |
595 | setCharacter(id, value, -1); | |
596 | } | |
597 | ||
598 | /** | |
599 | * Set the value associated to the given id as a {@link Character}. | |
600 | * | |
601 | * @param id | |
602 | * the id of the value to set | |
603 | * @param value | |
604 | * the value | |
605 | * @param item | |
606 | * the item number to get for an array of values, or -1 for | |
607 | * non-arrays | |
608 | * | |
609 | */ | |
610 | public void setCharacter(E id, char value, int item) { | |
611 | setString(id, BundleHelper.fromCharacter(value), item); | |
612 | } | |
613 | ||
b3aad1f9 | 614 | /** |
80500544 NR |
615 | * Return the value associated to the given id as a colour if it is found |
616 | * and can be parsed. | |
617 | * <p> | |
618 | * The returned value is an ARGB value. | |
13bfeea6 NR |
619 | * <p> |
620 | * If no value is associated, take the default one if any. | |
b3aad1f9 | 621 | * |
db31c358 NR |
622 | * @param id |
623 | * the id of the value to get | |
b3aad1f9 NR |
624 | * |
625 | * @return the associated value | |
626 | */ | |
80500544 | 627 | public Integer getColor(E id) { |
d5026c09 NR |
628 | return BundleHelper.parseColor(getString(id), -1); |
629 | } | |
630 | ||
631 | /** | |
632 | * Return the value associated to the given id as a colour if it is found | |
633 | * and can be parsed. | |
634 | * <p> | |
635 | * The returned value is an ARGB value. | |
636 | * <p> | |
637 | * If no value is associated, take the default one if any. | |
638 | * | |
639 | * @param id | |
640 | * the id of the value to get | |
856f5898 NR |
641 | * @param def |
642 | * the default value when it is not present in the config file or | |
643 | * if it is not a char value | |
d5026c09 NR |
644 | * |
645 | * @return the associated value | |
646 | */ | |
647 | public int getColor(E id, int def) { | |
648 | Integer value = getColor(id); | |
649 | if (value != null) { | |
650 | return value; | |
651 | } | |
652 | ||
653 | return def; | |
654 | } | |
655 | ||
656 | /** | |
657 | * Return the value associated to the given id as a colour if it is found | |
658 | * and can be parsed. | |
659 | * <p> | |
660 | * The returned value is an ARGB value. | |
661 | * <p> | |
662 | * If no value is associated, take the default one if any. | |
663 | * | |
664 | * @param id | |
665 | * the id of the value to get | |
856f5898 NR |
666 | * @param def |
667 | * the default value when it is not present in the config file or | |
668 | * if it is not a char value | |
669 | * @param item | |
670 | * the item number to get for an array of values, or -1 for | |
671 | * non-arrays | |
d5026c09 NR |
672 | * |
673 | * @return the associated value | |
674 | */ | |
675 | public Integer getColor(E id, int def, int item) { | |
676 | String value = getString(id); | |
677 | if (value != null) { | |
678 | return BundleHelper.parseColor(value, item); | |
679 | } | |
680 | ||
681 | return def; | |
b3aad1f9 NR |
682 | } |
683 | ||
62c9ec78 | 684 | /** |
80500544 NR |
685 | * Set the value associated to the given id as a colour. |
686 | * <p> | |
3bfc1d20 | 687 | * The value is a BGRA value. |
62c9ec78 | 688 | * |
db31c358 NR |
689 | * @param id |
690 | * the id of the value to set | |
691 | * @param color | |
80500544 | 692 | * the new colour |
62c9ec78 | 693 | */ |
80500544 | 694 | public void setColor(E id, Integer color) { |
d5026c09 NR |
695 | setColor(id, color, -1); |
696 | } | |
697 | ||
698 | /** | |
699 | * Set the value associated to the given id as a Color. | |
700 | * | |
701 | * @param id | |
702 | * the id of the value to set | |
703 | * @param value | |
704 | * the value | |
705 | * @param item | |
706 | * the item number to get for an array of values, or -1 for | |
707 | * non-arrays | |
708 | * | |
709 | */ | |
710 | public void setColor(E id, int value, int item) { | |
711 | setString(id, BundleHelper.fromColor(value), item); | |
62c9ec78 NR |
712 | } |
713 | ||
7c192d3c NR |
714 | /** |
715 | * Return the value associated to the given id as a list of values if it is | |
716 | * found and can be parsed. | |
13bfeea6 NR |
717 | * <p> |
718 | * If no value is associated, take the default one if any. | |
7c192d3c NR |
719 | * |
720 | * @param id | |
721 | * the id of the value to get | |
722 | * | |
723 | * @return the associated list, empty if the value is empty, NULL if it is | |
724 | * not found or cannot be parsed as a list | |
725 | */ | |
726 | public List<String> getList(E id) { | |
d5026c09 NR |
727 | return BundleHelper.parseList(getString(id), -1); |
728 | } | |
729 | ||
730 | /** | |
731 | * Return the value associated to the given id as a list of values if it is | |
732 | * found and can be parsed. | |
733 | * <p> | |
734 | * If no value is associated, take the default one if any. | |
735 | * | |
736 | * @param id | |
737 | * the id of the value to get | |
856f5898 NR |
738 | * @param def |
739 | * the default value when it is not present in the config file or | |
740 | * if it is not a char value | |
d5026c09 NR |
741 | * |
742 | * @return the associated list, empty if the value is empty, NULL if it is | |
743 | * not found or cannot be parsed as a list | |
744 | */ | |
745 | public List<String> getList(E id, List<String> def) { | |
746 | List<String> value = getList(id); | |
747 | if (value != null) { | |
748 | return value; | |
749 | } | |
750 | ||
751 | return def; | |
752 | } | |
753 | ||
754 | /** | |
755 | * Return the value associated to the given id as a list of values if it is | |
756 | * found and can be parsed. | |
757 | * <p> | |
758 | * If no value is associated, take the default one if any. | |
759 | * | |
760 | * @param id | |
761 | * the id of the value to get | |
856f5898 NR |
762 | * @param def |
763 | * the default value when it is not present in the config file or | |
764 | * if it is not a char value | |
765 | * @param item | |
766 | * the item number to get for an array of values, or -1 for | |
767 | * non-arrays | |
d5026c09 NR |
768 | * |
769 | * @return the associated list, empty if the value is empty, NULL if it is | |
770 | * not found or cannot be parsed as a list | |
771 | */ | |
772 | public List<String> getList(E id, List<String> def, int item) { | |
773 | String value = getString(id); | |
774 | if (value != null) { | |
775 | return BundleHelper.parseList(value, item); | |
776 | } | |
777 | ||
778 | return def; | |
7c192d3c NR |
779 | } |
780 | ||
781 | /** | |
782 | * Set the value associated to the given id as a list of values. | |
783 | * | |
784 | * @param id | |
785 | * the id of the value to set | |
786 | * @param list | |
787 | * the new list of values | |
788 | */ | |
789 | public void setList(E id, List<String> list) { | |
d5026c09 NR |
790 | setList(id, list, -1); |
791 | } | |
792 | ||
793 | /** | |
794 | * Set the value associated to the given id as a {@link List}. | |
795 | * | |
796 | * @param id | |
797 | * the id of the value to set | |
798 | * @param value | |
799 | * the value | |
800 | * @param item | |
801 | * the item number to get for an array of values, or -1 for | |
802 | * non-arrays | |
803 | * | |
804 | */ | |
805 | public void setList(E id, List<String> value, int item) { | |
806 | setString(id, BundleHelper.fromList(value), item); | |
7c192d3c NR |
807 | } |
808 | ||
487926f7 NR |
809 | /** |
810 | * Create/update the .properties file. | |
811 | * <p> | |
812 | * Will use the most likely candidate as base if the file does not already | |
813 | * exists and this resource is translatable (for instance, "en_US" will use | |
814 | * "en" as a base if the resource is a translation file). | |
815 | * <p> | |
816 | * Will update the files in {@link Bundles#getDirectory()}; it <b>MUST</b> | |
817 | * be set. | |
818 | * | |
819 | * @throws IOException | |
820 | * in case of IO errors | |
821 | */ | |
822 | public void updateFile() throws IOException { | |
823 | updateFile(Bundles.getDirectory()); | |
824 | } | |
825 | ||
ec1f3444 | 826 | /** |
80383c14 NR |
827 | * Create/update the .properties file. |
828 | * <p> | |
829 | * Will use the most likely candidate as base if the file does not already | |
830 | * exists and this resource is translatable (for instance, "en_US" will use | |
831 | * "en" as a base if the resource is a translation file). | |
ec1f3444 NR |
832 | * |
833 | * @param path | |
487926f7 NR |
834 | * the path where the .properties files are, <b>MUST NOT</b> be |
835 | * NULL | |
ec1f3444 NR |
836 | * |
837 | * @throws IOException | |
838 | * in case of IO errors | |
839 | */ | |
840 | public void updateFile(String path) throws IOException { | |
841 | File file = getUpdateFile(path); | |
842 | ||
843 | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( | |
844 | new FileOutputStream(file), "UTF-8")); | |
845 | ||
846 | writeHeader(writer); | |
847 | writer.write("\n"); | |
848 | writer.write("\n"); | |
849 | ||
850 | for (Field field : type.getDeclaredFields()) { | |
851 | Meta meta = field.getAnnotation(Meta.class); | |
852 | if (meta != null) { | |
cd0c27d2 | 853 | E id = Enum.valueOf(type, field.getName()); |
ec1f3444 NR |
854 | String info = getMetaInfo(meta); |
855 | ||
856 | if (info != null) { | |
857 | writer.write(info); | |
858 | writer.write("\n"); | |
859 | } | |
860 | ||
861 | writeValue(writer, id); | |
862 | } | |
863 | } | |
864 | ||
865 | writer.close(); | |
866 | } | |
867 | ||
e8aa5bf9 NR |
868 | /** |
869 | * Delete the .properties file. | |
870 | * <p> | |
871 | * Will use the most likely candidate as base if the file does not already | |
872 | * exists and this resource is translatable (for instance, "en_US" will use | |
873 | * "en" as a base if the resource is a translation file). | |
874 | * <p> | |
875 | * Will delete the files in {@link Bundles#getDirectory()}; it <b>MUST</b> | |
876 | * be set. | |
877 | * | |
878 | * @return TRUE if the file was deleted | |
879 | */ | |
880 | public boolean deleteFile() { | |
881 | return deleteFile(Bundles.getDirectory()); | |
882 | } | |
883 | ||
884 | /** | |
885 | * Delete the .properties file. | |
886 | * <p> | |
887 | * Will use the most likely candidate as base if the file does not already | |
888 | * exists and this resource is translatable (for instance, "en_US" will use | |
889 | * "en" as a base if the resource is a translation file). | |
890 | * | |
891 | * @param path | |
892 | * the path where the .properties files are, <b>MUST NOT</b> be | |
893 | * NULL | |
894 | * | |
895 | * @return TRUE if the file was deleted | |
896 | */ | |
897 | public boolean deleteFile(String path) { | |
898 | File file = getUpdateFile(path); | |
899 | return file.delete(); | |
900 | } | |
901 | ||
db31c358 NR |
902 | /** |
903 | * The description {@link TransBundle}, that is, a {@link TransBundle} | |
904 | * dedicated to the description of the values of the given {@link Bundle} | |
905 | * (can be NULL). | |
906 | * | |
907 | * @return the description {@link TransBundle} | |
908 | */ | |
909 | public TransBundle<E> getDescriptionBundle() { | |
910 | return descriptionBundle; | |
911 | } | |
912 | ||
80383c14 NR |
913 | /** |
914 | * Reload the {@link Bundle} data files. | |
e9ca6bb8 NR |
915 | * |
916 | * @param resetToDefault | |
917 | * reset to the default configuration (do not look into the | |
918 | * possible user configuration files, only take the original | |
919 | * configuration) | |
80383c14 | 920 | */ |
e9ca6bb8 | 921 | public void reload(boolean resetToDefault) { |
db31c358 | 922 | setBundle(keyType, Locale.getDefault(), resetToDefault); |
80383c14 NR |
923 | } |
924 | ||
ec1f3444 NR |
925 | /** |
926 | * Check if the internal map contains the given key. | |
927 | * | |
928 | * @param key | |
929 | * the key to check for | |
930 | * | |
931 | * @return true if it does | |
932 | */ | |
933 | protected boolean containsKey(String key) { | |
487926f7 | 934 | return changeMap.containsKey(key) || map.containsKey(key); |
ec1f3444 NR |
935 | } |
936 | ||
06359ad5 | 937 | /** |
b9839223 | 938 | * The default {@link Meta#def()} value for the given enumeration name. |
06359ad5 NR |
939 | * |
940 | * @param id | |
941 | * the enumeration name (the "id") | |
942 | * | |
943 | * @return the def value in the {@link MetaInfo} or "" if none (never NULL) | |
944 | */ | |
945 | protected String getMetaDef(String id) { | |
946 | String rep = ""; | |
947 | try { | |
948 | Meta meta = type.getDeclaredField(id).getAnnotation(Meta.class); | |
949 | rep = meta.def(); | |
950 | } catch (NoSuchFieldException e) { | |
951 | } catch (SecurityException e) { | |
952 | } | |
953 | ||
954 | if (rep == null) { | |
955 | rep = ""; | |
956 | } | |
957 | ||
958 | return rep; | |
959 | } | |
960 | ||
ec1f3444 | 961 | /** |
13bfeea6 NR |
962 | * Get the value for the given key if it exists in the internal map, or |
963 | * <tt>def</tt> if not. | |
06359ad5 NR |
964 | * <p> |
965 | * DO NOT get the default meta value (MetaInfo.def()). | |
ec1f3444 NR |
966 | * |
967 | * @param key | |
968 | * the key to check for | |
13bfeea6 NR |
969 | * @param def |
970 | * the default value when it is not present in the internal map | |
ec1f3444 | 971 | * |
13bfeea6 | 972 | * @return the value, or <tt>def</tt> if not found |
ec1f3444 | 973 | */ |
13bfeea6 | 974 | protected String getString(String key, String def) { |
62c9ec78 NR |
975 | if (changeMap.containsKey(key)) { |
976 | return changeMap.get(key); | |
977 | } | |
978 | ||
487926f7 NR |
979 | if (map.containsKey(key)) { |
980 | return map.get(key); | |
ec1f3444 NR |
981 | } |
982 | ||
13bfeea6 | 983 | return def; |
ec1f3444 NR |
984 | } |
985 | ||
62c9ec78 NR |
986 | /** |
987 | * Set the value for this key, in the change map (it is kept in memory, not | |
988 | * yet on disk). | |
989 | * | |
990 | * @param key | |
991 | * the key | |
992 | * @param value | |
993 | * the associated value | |
994 | */ | |
995 | protected void setString(String key, String value) { | |
487926f7 | 996 | changeMap.put(key, value == null ? null : value.trim()); |
62c9ec78 NR |
997 | } |
998 | ||
ec1f3444 NR |
999 | /** |
1000 | * Return formated, display-able information from the {@link Meta} field | |
1001 | * given. Each line will always starts with a "#" character. | |
1002 | * | |
1003 | * @param meta | |
1004 | * the {@link Meta} field | |
1005 | * | |
1006 | * @return the information to display or NULL if none | |
1007 | */ | |
1008 | protected String getMetaInfo(Meta meta) { | |
db31c358 NR |
1009 | String desc = meta.description(); |
1010 | boolean group = meta.group(); | |
1011 | Meta.Format format = meta.format(); | |
1012 | String[] list = meta.list(); | |
1013 | boolean nullable = meta.nullable(); | |
e8aa5bf9 | 1014 | String def = meta.def(); |
db31c358 | 1015 | boolean array = meta.array(); |
ec1f3444 | 1016 | |
db31c358 | 1017 | // Default, empty values -> NULL |
d18e136e | 1018 | if (desc.length() + list.length + def.length() == 0 && !group |
b15a4985 | 1019 | && nullable && format == Format.STRING) { |
ec1f3444 | 1020 | return null; |
db31c358 | 1021 | } |
ec1f3444 NR |
1022 | |
1023 | StringBuilder builder = new StringBuilder(); | |
b15a4985 NR |
1024 | for (String line : desc.split("\n")) { |
1025 | builder.append("# ").append(line).append("\n"); | |
db31c358 | 1026 | } |
ec1f3444 | 1027 | |
db31c358 | 1028 | if (group) { |
b15a4985 | 1029 | builder.append("# This item is used as a group, its content is not expected to be used."); |
db31c358 | 1030 | } else { |
b15a4985 NR |
1031 | builder.append("# (FORMAT: ").append(format) |
1032 | .append(nullable ? "" : ", required"); | |
d18e136e | 1033 | builder.append(") "); |
db31c358 NR |
1034 | |
1035 | if (list.length > 0) { | |
b15a4985 NR |
1036 | builder.append("\n# ALLOWED VALUES: "); |
1037 | boolean first = true; | |
db31c358 | 1038 | for (String value : list) { |
b15a4985 NR |
1039 | if (!first) { |
1040 | builder.append(", "); | |
1041 | } | |
1042 | builder.append(BundleHelper.escape(value)); | |
1043 | first = false; | |
db31c358 | 1044 | } |
ec1f3444 NR |
1045 | } |
1046 | ||
db31c358 | 1047 | if (array) { |
d5026c09 | 1048 | builder.append("\n# (This item accepts a list of ^escaped comma-separated values)"); |
ec1f3444 NR |
1049 | } |
1050 | } | |
1051 | ||
ec1f3444 NR |
1052 | return builder.toString(); |
1053 | } | |
1054 | ||
1055 | /** | |
1056 | * The display name used in the <tt>.properties file</tt>. | |
1057 | * | |
1058 | * @return the name | |
1059 | */ | |
1060 | protected String getBundleDisplayName() { | |
db31c358 | 1061 | return keyType.toString(); |
ec1f3444 NR |
1062 | } |
1063 | ||
1064 | /** | |
1065 | * Write the header found in the configuration <tt>.properties</tt> file of | |
1066 | * this {@link Bundles}. | |
1067 | * | |
1068 | * @param writer | |
1069 | * the {@link Writer} to write the header in | |
1070 | * | |
1071 | * @throws IOException | |
1072 | * in case of IO error | |
1073 | */ | |
1074 | protected void writeHeader(Writer writer) throws IOException { | |
1075 | writer.write("# " + getBundleDisplayName() + "\n"); | |
1076 | writer.write("#\n"); | |
1077 | } | |
1078 | ||
1079 | /** | |
b15a4985 NR |
1080 | * Write the given data to the config file, i.e., "MY_ID = my_curent_value" |
1081 | * followed by a new line. | |
1082 | * <p> | |
1083 | * Will prepend a # sign if the is is not set (see | |
1084 | * {@link Bundle#isSet(Enum, boolean)}). | |
ec1f3444 NR |
1085 | * |
1086 | * @param writer | |
1087 | * the {@link Writer} to write into | |
1088 | * @param id | |
1089 | * the id to write | |
1090 | * | |
1091 | * @throws IOException | |
1092 | * in case of IO error | |
1093 | */ | |
1094 | protected void writeValue(Writer writer, E id) throws IOException { | |
b15a4985 NR |
1095 | boolean set = isSet(id, false); |
1096 | writeValue(writer, id.name(), getString(id), set); | |
ec1f3444 NR |
1097 | } |
1098 | ||
1099 | /** | |
1100 | * Write the given data to the config file, i.e., "MY_ID = my_curent_value" | |
b15a4985 NR |
1101 | * followed by a new line. |
1102 | * <p> | |
1103 | * Will prepend a # sign if the is is not set. | |
ec1f3444 NR |
1104 | * |
1105 | * @param writer | |
1106 | * the {@link Writer} to write into | |
1107 | * @param id | |
1108 | * the id to write | |
1109 | * @param value | |
1110 | * the id's value | |
b15a4985 NR |
1111 | * @param set |
1112 | * the value is set in this {@link Bundle} | |
ec1f3444 NR |
1113 | * |
1114 | * @throws IOException | |
1115 | * in case of IO error | |
1116 | */ | |
b15a4985 NR |
1117 | protected void writeValue(Writer writer, String id, String value, |
1118 | boolean set) throws IOException { | |
1119 | ||
1120 | if (!set) { | |
1121 | writer.write('#'); | |
1122 | } | |
1123 | ||
ec1f3444 NR |
1124 | writer.write(id); |
1125 | writer.write(" = "); | |
1126 | ||
1127 | if (value == null) { | |
1128 | value = ""; | |
1129 | } | |
1130 | ||
009196a4 | 1131 | String[] lines = value.replaceAll("\t", "\\\\\\t").split("\n"); |
ec1f3444 NR |
1132 | for (int i = 0; i < lines.length; i++) { |
1133 | writer.write(lines[i]); | |
1134 | if (i < lines.length - 1) { | |
1135 | writer.write("\\n\\"); | |
1136 | } | |
1137 | writer.write("\n"); | |
1138 | } | |
1139 | } | |
1140 | ||
1141 | /** | |
1142 | * Return the source file for this {@link Bundles} from the given path. | |
1143 | * | |
1144 | * @param path | |
1145 | * the path where the .properties files are | |
1146 | * | |
1147 | * @return the source {@link File} | |
ec1f3444 NR |
1148 | */ |
1149 | protected File getUpdateFile(String path) { | |
db31c358 | 1150 | return new File(path, keyType.name() + ".properties"); |
ec1f3444 NR |
1151 | } |
1152 | ||
1153 | /** | |
62c9ec78 | 1154 | * Change the currently used bundle, and reset all changes. |
ec1f3444 NR |
1155 | * |
1156 | * @param name | |
1157 | * the name of the bundle to load | |
1158 | * @param locale | |
1159 | * the {@link Locale} to use | |
e9ca6bb8 NR |
1160 | * @param resetToDefault |
1161 | * reset to the default configuration (do not look into the | |
1162 | * possible user configuration files, only take the original | |
1163 | * configuration) | |
ec1f3444 | 1164 | */ |
e9ca6bb8 | 1165 | protected void setBundle(Enum<?> name, Locale locale, boolean resetToDefault) { |
62c9ec78 | 1166 | changeMap.clear(); |
ec1f3444 | 1167 | String dir = Bundles.getDirectory(); |
e8aa5bf9 | 1168 | String bname = type.getPackage().getName() + "." + name.name(); |
ec1f3444 | 1169 | |
487926f7 | 1170 | boolean found = false; |
e9ca6bb8 | 1171 | if (!resetToDefault && dir != null) { |
ec1f3444 | 1172 | try { |
712ddafb | 1173 | // Look into Bundles.getDirectory() for .properties files |
ec1f3444 NR |
1174 | File file = getPropertyFile(dir, name.name(), locale); |
1175 | if (file != null) { | |
712ddafb NR |
1176 | InputStream in = new FileInputStream(file); |
1177 | try { | |
1178 | Reader reader = new InputStreamReader(in, "UTF-8"); | |
1179 | try { | |
1180 | resetMap(new PropertyResourceBundle(reader)); | |
1181 | } finally { | |
1182 | reader.close(); | |
1183 | } | |
1184 | } finally { | |
1185 | in.close(); | |
1186 | } | |
487926f7 | 1187 | found = true; |
ec1f3444 NR |
1188 | } |
1189 | } catch (IOException e) { | |
1190 | e.printStackTrace(); | |
1191 | } | |
1192 | } | |
1193 | ||
487926f7 | 1194 | if (!found) { |
e8aa5bf9 | 1195 | // Look into the package itself for resources |
e9ca6bb8 | 1196 | try { |
487926f7 NR |
1197 | resetMap(ResourceBundle |
1198 | .getBundle(bname, locale, type.getClassLoader(), | |
1199 | new FixedResourceBundleControl())); | |
e8aa5bf9 NR |
1200 | found = true; |
1201 | } catch (MissingResourceException e) { | |
e9ca6bb8 | 1202 | } catch (Exception e) { |
e8aa5bf9 | 1203 | e.printStackTrace(); |
487926f7 NR |
1204 | } |
1205 | } | |
e8aa5bf9 NR |
1206 | |
1207 | if (!found) { | |
1208 | // We have no bundle for this Bundle | |
1209 | System.err.println("No bundle found for: " + bname); | |
1210 | resetMap(null); | |
1211 | } | |
487926f7 NR |
1212 | } |
1213 | ||
1214 | /** | |
efba9850 | 1215 | * Reset the backing map to the content of the given bundle, or with NULL |
b15a4985 | 1216 | * values if bundle is NULL. |
487926f7 NR |
1217 | * |
1218 | * @param bundle | |
1219 | * the bundle to copy | |
1220 | */ | |
b771aed5 | 1221 | protected void resetMap(ResourceBundle bundle) { |
487926f7 | 1222 | this.map.clear(); |
b9839223 NR |
1223 | if (bundle != null) { |
1224 | for (Field field : type.getDeclaredFields()) { | |
1225 | try { | |
1226 | Meta meta = field.getAnnotation(Meta.class); | |
1227 | if (meta != null) { | |
1228 | E id = Enum.valueOf(type, field.getName()); | |
1229 | String value = bundle.getString(id.name()); | |
1230 | this.map.put(id.name(), | |
1231 | value == null ? null : value.trim()); | |
e8aa5bf9 | 1232 | } |
b9839223 | 1233 | } catch (MissingResourceException e) { |
487926f7 | 1234 | } |
e9ca6bb8 NR |
1235 | } |
1236 | } | |
1237 | } | |
cd0c27d2 | 1238 | |
e9ca6bb8 NR |
1239 | /** |
1240 | * Take a snapshot of the changes in memory in this {@link Bundle} made by | |
1241 | * the "set" methods ( {@link Bundle#setString(Enum, String)}...) at the | |
1242 | * current time. | |
1243 | * | |
487926f7 | 1244 | * @return a snapshot to use with {@link Bundle#restoreSnapshot(Object)} |
e9ca6bb8 | 1245 | */ |
487926f7 | 1246 | public Object takeSnapshot() { |
e9ca6bb8 NR |
1247 | return new HashMap<String, String>(changeMap); |
1248 | } | |
1249 | ||
1250 | /** | |
1251 | * Restore a snapshot taken with {@link Bundle}, or reset the current | |
1252 | * changes if the snapshot is NULL. | |
1253 | * | |
1254 | * @param snap | |
1255 | * the snapshot or NULL | |
1256 | */ | |
1257 | @SuppressWarnings("unchecked") | |
487926f7 | 1258 | public void restoreSnapshot(Object snap) { |
e9ca6bb8 NR |
1259 | if (snap == null) { |
1260 | changeMap.clear(); | |
1261 | } else { | |
1262 | if (snap instanceof Map) { | |
1263 | changeMap = (Map<String, String>) snap; | |
1264 | } else { | |
d827da2a | 1265 | throw new RuntimeException( |
e9ca6bb8 NR |
1266 | "Restoring changes in a Bundle must be done on a changes snapshot, " |
1267 | + "or NULL to discard current changes"); | |
1268 | } | |
ec1f3444 NR |
1269 | } |
1270 | } | |
1271 | ||
1272 | /** | |
1273 | * Return the resource file that is closer to the {@link Locale}. | |
1274 | * | |
1275 | * @param dir | |
db31c358 | 1276 | * the directory to look into |
ec1f3444 | 1277 | * @param name |
db31c358 | 1278 | * the file base name (without <tt>.properties</tt>) |
ec1f3444 NR |
1279 | * @param locale |
1280 | * the {@link Locale} | |
1281 | * | |
1282 | * @return the closest match or NULL if none | |
1283 | */ | |
1284 | private File getPropertyFile(String dir, String name, Locale locale) { | |
1285 | List<String> locales = new ArrayList<String>(); | |
1286 | if (locale != null) { | |
1287 | String country = locale.getCountry() == null ? "" : locale | |
1288 | .getCountry(); | |
1289 | String language = locale.getLanguage() == null ? "" : locale | |
1290 | .getLanguage(); | |
1291 | if (!language.isEmpty() && !country.isEmpty()) { | |
1292 | locales.add("_" + language + "-" + country); | |
1293 | } | |
1294 | if (!language.isEmpty()) { | |
1295 | locales.add("_" + language); | |
1296 | } | |
1297 | } | |
1298 | ||
1299 | locales.add(""); | |
1300 | ||
1301 | File file = null; | |
1302 | for (String loc : locales) { | |
1303 | file = new File(dir, name + loc + ".properties"); | |
1304 | if (file.exists()) { | |
1305 | break; | |
ec1f3444 | 1306 | } |
d827da2a | 1307 | |
cd0c27d2 | 1308 | file = null; |
ec1f3444 NR |
1309 | } |
1310 | ||
1311 | return file; | |
1312 | } | |
1313 | } |