LocalizedKeywords.java

  1. package org.jbehave.core.i18n;

  2. import static java.util.ResourceBundle.getBundle;

  3. import java.net.URLClassLoader;
  4. import java.util.HashMap;
  5. import java.util.Locale;
  6. import java.util.Map;
  7. import java.util.MissingResourceException;
  8. import java.util.ResourceBundle;

  9. import org.apache.commons.lang3.StringUtils;
  10. import org.jbehave.core.configuration.Keywords;

  11. /**
  12.  * Adds i18n support to Keywords, allowing to read the keywords from resource
  13.  * bundles for a given locale.
  14.  */
  15. public class LocalizedKeywords extends Keywords {

  16.     private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
  17.     private static final String DEFAULT_BUNDLE_NAME = "i18n/keywords";
  18.     private static final ClassLoader DEFAULT_CLASS_LOADER = LocalizedKeywords.class.getClassLoader();
  19.     private final Locale locale;

  20.     public LocalizedKeywords() {
  21.         this(DEFAULT_LOCALE);
  22.     }

  23.     public LocalizedKeywords(Locale locale) {
  24.         this(locale, DEFAULT_BUNDLE_NAME, DEFAULT_CLASS_LOADER);
  25.     }

  26.     public LocalizedKeywords(Locale locale, Locale baseLocale) {
  27.         this(locale, baseLocale, DEFAULT_BUNDLE_NAME, DEFAULT_CLASS_LOADER);
  28.     }

  29.     public LocalizedKeywords(Locale locale, String bundleName, ClassLoader classLoader) {
  30.         this(locale, Locale.ENGLISH, bundleName, classLoader);
  31.     }

  32.     public LocalizedKeywords(Locale locale, Locale baseLocale, String bundleName, ClassLoader classLoader) {
  33.         this(locale, baseLocale, bundleName, bundleName, classLoader);
  34.     }

  35.     public LocalizedKeywords(Locale locale, String bundleName, String baseBundleName) {
  36.         this(locale, bundleName, baseBundleName, DEFAULT_CLASS_LOADER);
  37.     }

  38.     public LocalizedKeywords(Locale locale, String bundleName, String baseBundleName, ClassLoader classLoader) {
  39.         this(locale, locale, bundleName, baseBundleName, classLoader);
  40.     }

  41.     public LocalizedKeywords(Locale locale, Locale baseLocale, String bundleName, String baseBundleName,
  42.             ClassLoader classLoader) {
  43.         super(keywords(locale, bundleName, baseLocale, baseBundleName, classLoader));
  44.         this.locale = locale;
  45.     }

  46.     private static Map<String, String> keywords(Locale locale, String bundleName, Locale baseLocale,
  47.                                                 String baseBundleName, ClassLoader classLoader) {
  48.         ResourceBundle bundle = findBunde(bundleName, locale, classLoader);
  49.         ResourceBundle baseBundle = findBunde(baseBundleName, baseLocale, classLoader);
  50.         Map<String, String> keywords = new HashMap<>();
  51.         for (String key : KEYWORDS) {
  52.             try {
  53.                 keywords.put(key, bundle.getString(key));
  54.             } catch (MissingResourceException e) {
  55.                 if (locale == baseLocale && bundleName.equals(baseBundleName)) {
  56.                     throw new LocalizedKeywordNotFound(key, bundleName, locale);
  57.                 } else {
  58.                     keywords.put(key, baseBundle.getString(key));
  59.                 }
  60.             }
  61.         }
  62.         return keywords;
  63.     }

  64.     private static ResourceBundle findBunde(String bundleName, Locale locale, ClassLoader classLoader) {
  65.         String name = bundleName.trim();
  66.         try {
  67.             if (classLoader != null) {
  68.                 return getBundle(name, locale, classLoader);
  69.             }
  70.             return getBundle(name, locale);
  71.         } catch (MissingResourceException e) {
  72.             throw new ResourceBundleNotFound(name, locale, classLoader, e);
  73.         }
  74.     }

  75.     public Locale getLocale() {
  76.         return locale;
  77.     }

  78.     @SuppressWarnings("serial")
  79.     public static class ResourceBundleNotFound extends RuntimeException {

  80.         public static final String PATH_SEPARATOR = ";";

  81.         public ResourceBundleNotFound(String bundleName, Locale locale, ClassLoader classLoader,
  82.                                       MissingResourceException cause) {
  83.             super("Resource bundle " + bundleName + " not found for locale " + locale + " in classLoader "
  84.                     + asString(classLoader), cause);
  85.         }

  86.         private static String asString(ClassLoader classLoader) {
  87.             if (classLoader instanceof URLClassLoader) {
  88.                 return StringUtils.join(((URLClassLoader)classLoader).getURLs(), PATH_SEPARATOR);
  89.             }
  90.             return classLoader.toString();
  91.         }

  92.     }

  93.     @SuppressWarnings("serial")
  94.     public static class LocalizedKeywordNotFound extends RuntimeException {

  95.         public LocalizedKeywordNotFound(String key, String bundleName, Locale locale) {
  96.             super("Keyword " + key + " not found for locale " + locale + " in bundle " + bundleName);
  97.         }

  98.     }

  99. }