1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package de.bea.domingo.i18n;
24
25 import java.text.DateFormat;
26 import java.text.MessageFormat;
27 import java.text.ParseException;
28 import java.util.Date;
29 import java.util.Locale;
30 import java.util.MissingResourceException;
31 import java.util.Random;
32 import java.util.ResourceBundle;
33
34 /***
35 * A class to simplify extracting localized strings, icons
36 * and other common resources from a ResourceBundle.
37 *
38 * @author <a href=mailto:kriede@users.sourceforge.net>Kurt Riede</a>
39 */
40 public final class Resources {
41
42 /*** A pseudorandom numbers generator. */
43 private static final Random RANDOM = new Random();
44
45 /*** Local of Resources. */
46 private final Locale locale;
47
48 /*** Resource bundle referenced by manager. */
49 private ResourceBundle bundle;
50
51 /*** Base name of resource bundle. */
52 private final String baseName;
53
54 /*** ClassLoader from which to load resources. */
55 private final ClassLoader classLoader;
56
57 /*** Whether an exception should be thrown in case of an unknown resource or not. */
58 private boolean fFailOnError;
59
60 /***
61 * Constructor that builds a manager in default locale.
62 *
63 * @param theBaseName the base name of ResourceBundle
64 */
65 public Resources(final String theBaseName) {
66 this(theBaseName, Locale.getDefault(), null);
67 }
68
69 /***
70 * Constructor that builds a manager in default locale
71 * using specified ClassLoader.
72 *
73 * @param theBaseName the base name of ResourceBundle
74 * @param theClassLoader the classLoader to load ResourceBundle from
75 */
76 public Resources(final String theBaseName, final ClassLoader theClassLoader) {
77 this(theBaseName, Locale.getDefault(), theClassLoader);
78 }
79
80 /***
81 * Constructor that builds a manager in specified locale.
82 *
83 * @param theBaseName the base name of ResourceBundle
84 * @param theLocale the Locale for resource bundle
85 */
86 public Resources(final String theBaseName, final Locale theLocale) {
87 this(theBaseName, theLocale, null);
88 }
89
90 /***
91 * Constructor that builds a manager in specified locale.
92 *
93 * @param theBaseName the base name of ResourceBundle
94 * @param theLocale the Locale for resource bundle
95 * @param theClassLoader the classLoader to load ResourceBundle from
96 */
97 public Resources(final String theBaseName, final Locale theLocale, final ClassLoader theClassLoader) {
98 if (null == theBaseName) {
99 throw new NullPointerException("baseName property is null");
100 }
101 if (null == theLocale) {
102 throw new NullPointerException("locale property is null");
103 }
104 baseName = theBaseName;
105 locale = theLocale;
106 classLoader = theClassLoader;
107 }
108
109 /***
110 * Whether an exception should be thrown in case of an unknown resource or
111 * not.
112 *
113 * @param failOnError <code>true</code> if an exception should be thrown
114 * in case of an unknown resource, else <code>false</code>
115 * @return the instance itself
116 */
117 public Resources withFailOnError(final boolean failOnError) {
118 this.fFailOnError = failOnError;
119 return this;
120 }
121
122 /***
123 * Retrieve a boolean from bundle.
124 *
125 * @param key the key of resource
126 * @param defaultValue the default value if key is missing
127 * @return the resource boolean
128 * @throws MissingResourceException if a resource wasn't found
129 */
130 public boolean getBoolean(final String key, final boolean defaultValue) throws MissingResourceException {
131 try {
132 return getBoolean(key);
133 } catch (final MissingResourceException mre) {
134 return defaultValue;
135 }
136 }
137
138 /***
139 * Retrieve a boolean from bundle.
140 *
141 * @param key the key of resource
142 * @return the resource boolean
143 * @throws MissingResourceException if a resource wasn't found
144 */
145 public boolean getBoolean(final String key) throws MissingResourceException {
146 final ResourceBundle newBundle = getBundle();
147 final String value = newBundle.getString(key);
148 return value.equalsIgnoreCase("true");
149 }
150
151 /***
152 * Retrieve a byte from bundle.
153 *
154 * @param key the key of resource
155 * @param defaultValue the default value if key is missing
156 * @return the resource byte
157 * @throws MissingResourceException if a resource wasn't found
158 */
159 public byte getByte(final String key, final byte defaultValue) throws MissingResourceException {
160 try {
161 return getByte(key);
162 } catch (final MissingResourceException mre) {
163 return defaultValue;
164 }
165 }
166
167 /***
168 * Retrieve a byte from bundle.
169 *
170 * @param key the key of resource
171 * @return the resource byte
172 * @throws MissingResourceException if a resource wasn't found
173 */
174 public byte getByte(final String key) throws MissingResourceException {
175 final ResourceBundle theBundle = getBundle();
176 final String value = theBundle.getString(key);
177 try {
178 return Byte.parseByte(value);
179 } catch (final NumberFormatException nfe) {
180 throw new MissingResourceException("Expecting a byte value but got " + value, String.class.getName(), key);
181 }
182 }
183
184 /***
185 * Retrieve a char from bundle.
186 *
187 * @param key the key of resource
188 * @param defaultValue the default value if key is missing
189 * @return the resource char
190 * @throws MissingResourceException if a resource wasn't found
191 */
192 public char getChar(final String key, final char defaultValue) throws MissingResourceException {
193 try {
194 return getChar(key);
195 } catch (final MissingResourceException mre) {
196 return defaultValue;
197 }
198 }
199
200 /***
201 * Retrieve a char from bundle.
202 *
203 * @param key the key of resource
204 * @return the resource char
205 * @throws MissingResourceException if a resource wasn't found
206 */
207 public char getChar(final String key) throws MissingResourceException {
208 final ResourceBundle theBundle = getBundle();
209 final String value = theBundle.getString(key);
210 if (1 != value.length()) {
211 throw new MissingResourceException("Expecting a char value but got " + value, String.class.getName(), key);
212 }
213 return value.charAt(0);
214 }
215
216 /***
217 * Retrieve a short from bundle.
218 *
219 * @param key the key of resource
220 * @param defaultValue the default value if key is missing
221 * @return the resource short
222 * @throws MissingResourceException if a resource wasn't found
223 */
224 public short getShort(final String key, final short defaultValue) throws MissingResourceException {
225 try {
226 return getShort(key);
227 } catch (final MissingResourceException mre) {
228 return defaultValue;
229 }
230 }
231
232 /***
233 * Retrieve a short from bundle.
234 *
235 * @param key the key of resource
236 * @return the resource short
237 * @throws MissingResourceException if a resource wasn't found
238 */
239 public short getShort(final String key) throws MissingResourceException {
240 final ResourceBundle theBundle = getBundle();
241 final String value = theBundle.getString(key);
242 try {
243 return Short.parseShort(value);
244 } catch (final NumberFormatException nfe) {
245 throw new MissingResourceException("Expecting a short value but got " + value, String.class.getName(), key);
246 }
247 }
248
249 /***
250 * Retrieve a integer from bundle.
251 *
252 * @param key the key of resource
253 * @param defaultValue the default value if key is missing
254 * @return the resource integer
255 * @throws MissingResourceException if a resource wasn't found
256 */
257 public int getInteger(final String key, final int defaultValue) throws MissingResourceException {
258 try {
259 return getInteger(key);
260 } catch (final MissingResourceException mre) {
261 return defaultValue;
262 }
263 }
264
265 /***
266 * Retrieve a integer from bundle.
267 *
268 * @param key the key of resource
269 * @return the resource integer
270 * @throws MissingResourceException if a resource wasn't found
271 */
272 public int getInteger(final String key) throws MissingResourceException {
273 final ResourceBundle theBundle = getBundle();
274 final String value = theBundle.getString(key);
275 try {
276 return Integer.parseInt(value);
277 } catch (final NumberFormatException nfe) {
278 throw new MissingResourceException("Expecting a integer value but got " + value, String.class.getName(), key);
279 }
280 }
281
282 /***
283 * Retrieve a long from bundle.
284 *
285 * @param key the key of resource
286 * @param defaultValue the default value if key is missing
287 * @return the resource long
288 * @throws MissingResourceException if a resource wasn't found
289 */
290 public long getLong(final String key, final long defaultValue) throws MissingResourceException {
291 try {
292 return getLong(key);
293 } catch (final MissingResourceException mre) {
294 return defaultValue;
295 }
296 }
297
298 /***
299 * Retrieve a long from bundle.
300 *
301 * @param key the key of resource
302 * @return the resource long
303 * @throws MissingResourceException if a resource wasn't found
304 */
305 public long getLong(final String key) throws MissingResourceException {
306 final ResourceBundle theBundle = getBundle();
307 final String value = theBundle.getString(key);
308 try {
309 return Long.parseLong(value);
310 } catch (final NumberFormatException nfe) {
311 throw new MissingResourceException("Expecting a long value but got " + value, String.class.getName(), key);
312 }
313 }
314
315 /***
316 * Retrieve a float from bundle.
317 *
318 * @param key the key of resource
319 * @param defaultValue the default value if key is missing
320 * @return the resource float
321 * @throws MissingResourceException if a resource wasn't found
322 */
323 public float getFloat(final String key, final float defaultValue) throws MissingResourceException {
324 try {
325 return getFloat(key);
326 } catch (final MissingResourceException mre) {
327 return defaultValue;
328 }
329 }
330
331 /***
332 * Retrieve a float from bundle.
333 *
334 * @param key the key of resource
335 * @return the resource float
336 * @throws MissingResourceException if a resource wasn't found
337 */
338 public float getFloat(final String key) throws MissingResourceException {
339 final ResourceBundle theBundle = getBundle();
340 final String value = theBundle.getString(key);
341 try {
342 return Float.parseFloat(value);
343 } catch (final NumberFormatException nfe) {
344 throw new MissingResourceException("Expecting a float value but got " + value, String.class.getName(), key);
345 }
346 }
347
348 /***
349 * Retrieve a double from bundle.
350 *
351 * @param key the key of resource
352 * @param defaultValue the default value if key is missing
353 * @return the resource double
354 * @throws MissingResourceException if a resource wasn't found
355 */
356 public double getDouble(final String key, final double defaultValue) throws MissingResourceException {
357 try {
358 return getDouble(key);
359 } catch (final MissingResourceException mre) {
360 return defaultValue;
361 }
362 }
363
364 /***
365 * Retrieve a double from bundle.
366 *
367 * @param key the key of resource
368 * @return the resource double
369 * @throws MissingResourceException if a resource wasn't found
370 */
371 public double getDouble(final String key) throws MissingResourceException {
372 final ResourceBundle theBundle = getBundle();
373 final String value = theBundle.getString(key);
374 try {
375 return Double.parseDouble(value);
376 } catch (final NumberFormatException nfe) {
377 throw new MissingResourceException("Expecting a double value but got " + value, String.class.getName(), key);
378 }
379 }
380
381 /***
382 * Retrieve a date from bundle.
383 *
384 * @param key the key of resource
385 * @param defaultValue the default value if key is missing
386 * @return the resource date
387 * @throws MissingResourceException if a resource wasn't found
388 */
389 public Date getDate(final String key, final Date defaultValue) throws MissingResourceException {
390 try {
391 return getDate(key);
392 } catch (final MissingResourceException mre) {
393 return defaultValue;
394 }
395 }
396
397 /***
398 * Retrieve a date from bundle.
399 *
400 * @param key the key of resource
401 * @return the resource date
402 * @throws MissingResourceException if a resource wasn't found
403 */
404 public Date getDate(final String key) throws MissingResourceException {
405 final ResourceBundle theBundle = getBundle();
406 final String value = theBundle.getString(key);
407 try {
408 final DateFormat format = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
409 return format.parse(value);
410 } catch (final ParseException pe) {
411 throw new MissingResourceException("Expecting a date value but got " + value, String.class.getName(), key);
412 }
413 }
414
415 /***
416 * Retrieve a time from bundle.
417 *
418 * @param key the key of resource
419 * @param defaultValue the default value if key is missing
420 * @return the resource time
421 * @throws MissingResourceException if a resource wasn't found
422 */
423 public Date getTime(final String key, final Date defaultValue) throws MissingResourceException {
424 try {
425 return getTime(key);
426 } catch (final MissingResourceException mre) {
427 return defaultValue;
428 }
429 }
430
431 /***
432 * Retrieve a time from bundle.
433 *
434 * @param key the key of resource
435 * @return the resource time
436 * @throws MissingResourceException if a resource wasn't found
437 */
438 public Date getTime(final String key) throws MissingResourceException {
439 final ResourceBundle theBundle = getBundle();
440 final String value = theBundle.getString(key);
441 try {
442 final DateFormat format = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
443 return format.parse(value);
444 } catch (final ParseException pe) {
445 throw new MissingResourceException("Expecting a time value but got " + value, String.class.getName(), key);
446 }
447 }
448
449 /***
450 * Retrieve a time from bundle.
451 *
452 * @param key the key of resource
453 * @param defaultValue the default value if key is missing
454 * @return the resource time
455 * @throws MissingResourceException if a resource wasn't found
456 */
457 public Date getDateTime(final String key, final Date defaultValue) throws MissingResourceException {
458 try {
459 return getDateTime(key);
460 } catch (final MissingResourceException mre) {
461 return defaultValue;
462 }
463 }
464
465 /***
466 * Retrieve a date + time from bundle.
467 *
468 * @param key the key of resource
469 * @return the resource date + time
470 * @throws MissingResourceException if a resource wasn't found
471 */
472 public Date getDateTime(final String key) throws MissingResourceException {
473 final ResourceBundle theBundle = getBundle();
474 final String value = theBundle.getString(key);
475 try {
476 final DateFormat format = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, locale);
477 return format.parse(value);
478 } catch (final ParseException pe) {
479 throw new MissingResourceException("Expecting a date/time value but got " + value, String.class.getName(), key);
480 }
481 }
482
483 /***
484 * Retrieve a raw string from bundle.
485 *
486 * @param key the key of resource
487 * @return the resource string
488 * @throws MissingResourceException if a resource wasn't found
489 */
490 public String getString(final String key) throws MissingResourceException {
491 final Object[] args = new Object[] {};
492 return format(key, args);
493 }
494
495 /***
496 * Retrieve a string from resource bundle and format it with specified arguments.
497 *
498 * @param key the key for resource
499 * @param arg1 an argument
500 * @return the formatted string
501 */
502 public String getString(final String key, final Object arg1) {
503 final Object[] args = new Object[] {arg1 };
504 return format(key, args);
505 }
506
507 /***
508 * Retrieve a string from resource bundle and format it with specified arguments.
509 *
510 * @param key the key for resource
511 * @param arg1 an argument
512 * @param arg2 an argument
513 * @return the formatted string
514 */
515 public String getString(final String key, final Object arg1, final Object arg2) {
516 final Object[] args = new Object[] {arg1, arg2 };
517 return format(key, args);
518 }
519
520 /***
521 * Retrieve a string from resource bundle and format it with specified arguments.
522 *
523 * @param key the key for resource
524 * @param arg1 an argument
525 * @param arg2 an argument
526 * @param arg3 an argument
527 * @return the formatted string
528 */
529 public String getString(final String key, final Object arg1, final Object arg2, final Object arg3) {
530 final Object[] args = new Object[] {arg1, arg2, arg3 };
531 return format(key, args);
532 }
533
534 /***
535 * Retrieve a string from resource bundle and format it with specified arguments.
536 *
537 * @param key the key for resource
538 * @param arg1 an argument
539 * @param arg2 an argument
540 * @param arg3 an argument
541 * @param arg4 an argument
542 * @return the formatted string
543 */
544 public String getString(final String key, final Object arg1, final Object arg2, final Object arg3, final Object arg4) {
545 final Object[] args = new Object[] {arg1, arg2, arg3, arg4 };
546 return format(key, args);
547 }
548
549 /***
550 * Retrieve a string from resource bundle and format it with specified arguments.
551 *
552 * @param key the key for resource
553 * @param args an array of arguments
554 * @return the formatted string
555 * @throws MissingResourceException if {@link #withFailOnError(boolean)} is true and the requested resource wasn't found
556 * @see #withFailOnError(boolean)
557 */
558 public String format(final String key, final Object[] args) throws MissingResourceException {
559 try {
560 final String pattern = getPatternString(key);
561 return MessageFormat.format(pattern, args);
562 } catch (final MissingResourceException mre) {
563 if (fFailOnError) {
564 throw mre;
565 }
566 final StringBuffer sb = new StringBuffer();
567 sb.append("Unknown resource. Bundle: '");
568 sb.append(baseName);
569 sb.append("' key: '");
570 sb.append(key);
571 sb.append("' arguments: '");
572 for (int i = 0; i < args.length; i++) {
573 if (0 != i) {
574 sb.append("', '");
575 }
576 sb.append(args[i]);
577 }
578 sb.append("' Reason: ");
579 sb.append(mre);
580 return sb.toString();
581 }
582 }
583
584 /***
585 * Retrieve underlying ResourceBundle.
586 * If bundle has not been loaded it will be loaded by this method.
587 * Access is given in case other resources need to be extracted
588 * that this Manager does not provide simplified access to.
589 *
590 * @return the ResourceBundle
591 * @throws MissingResourceException if an error occurs
592 */
593 public ResourceBundle getBundle() throws MissingResourceException {
594 if (null == bundle) {
595
596 ClassLoader theClassLoader = this.classLoader;
597 if (null == theClassLoader) {
598 theClassLoader = Thread.currentThread().getContextClassLoader();
599 }
600 if (null != theClassLoader) {
601 bundle = ResourceBundle.getBundle(baseName, locale, theClassLoader);
602 } else {
603 bundle = ResourceBundle.getBundle(baseName, locale);
604 }
605 }
606 return bundle;
607 }
608
609 /***
610 * Utility method to retrieve a string from ResourceBundle.
611 * If the key is a single string then that will be returned.
612 * If key refers to string array then a random string will be chosen.
613 * Other types cause an exception.
614 *
615 * @param key the key to resource
616 * @return the string resource
617 * @throws MissingResourceException if an error occurs
618 */
619 private String getPatternString(final String key) throws MissingResourceException {
620 final ResourceBundle theBundle = getBundle();
621 final Object object = theBundle.getObject(key);
622
623 if (object instanceof String) {
624 return (String) object;
625 } else if (object instanceof String[]) {
626
627 final String[] strings = (String[]) object;
628 return strings[RANDOM.nextInt(strings.length)];
629 } else {
630 throw new MissingResourceException("Unable to find resource of appropriate type.", String.class.getName(), key);
631 }
632 }
633 }