LocalizedKeywords.java
package org.jbehave.core.i18n;
import static java.util.ResourceBundle.getBundle;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.apache.commons.lang3.StringUtils;
import org.jbehave.core.configuration.Keywords;
/**
* Adds i18n support to Keywords, allowing to read the keywords from resource
* bundles for a given locale.
*/
public class LocalizedKeywords extends Keywords {
private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
private static final String DEFAULT_BUNDLE_NAME = "i18n/keywords";
private static final ClassLoader DEFAULT_CLASS_LOADER = LocalizedKeywords.class.getClassLoader();
private final Locale locale;
public LocalizedKeywords() {
this(DEFAULT_LOCALE);
}
public LocalizedKeywords(Locale locale) {
this(locale, DEFAULT_BUNDLE_NAME, DEFAULT_CLASS_LOADER);
}
public LocalizedKeywords(Locale locale, Locale baseLocale) {
this(locale, baseLocale, DEFAULT_BUNDLE_NAME, DEFAULT_CLASS_LOADER);
}
public LocalizedKeywords(Locale locale, String bundleName, ClassLoader classLoader) {
this(locale, Locale.ENGLISH, bundleName, classLoader);
}
public LocalizedKeywords(Locale locale, Locale baseLocale, String bundleName, ClassLoader classLoader) {
this(locale, baseLocale, bundleName, bundleName, classLoader);
}
public LocalizedKeywords(Locale locale, String bundleName, String baseBundleName) {
this(locale, bundleName, baseBundleName, DEFAULT_CLASS_LOADER);
}
public LocalizedKeywords(Locale locale, String bundleName, String baseBundleName, ClassLoader classLoader) {
this(locale, locale, bundleName, baseBundleName, classLoader);
}
public LocalizedKeywords(Locale locale, Locale baseLocale, String bundleName, String baseBundleName,
ClassLoader classLoader) {
super(keywords(locale, bundleName, baseLocale, baseBundleName, classLoader));
this.locale = locale;
}
private static Map<String, String> keywords(Locale locale, String bundleName, Locale baseLocale,
String baseBundleName, ClassLoader classLoader) {
ResourceBundle bundle = findBunde(bundleName, locale, classLoader);
ResourceBundle baseBundle = findBunde(baseBundleName, baseLocale, classLoader);
Map<String, String> keywords = new HashMap<>();
for (String key : KEYWORDS) {
try {
keywords.put(key, bundle.getString(key));
} catch (MissingResourceException e) {
if (locale == baseLocale && bundleName.equals(baseBundleName)) {
throw new LocalizedKeywordNotFound(key, bundleName, locale);
} else {
keywords.put(key, baseBundle.getString(key));
}
}
}
return keywords;
}
private static ResourceBundle findBunde(String bundleName, Locale locale, ClassLoader classLoader) {
String name = bundleName.trim();
try {
if (classLoader != null) {
return getBundle(name, locale, classLoader);
}
return getBundle(name, locale);
} catch (MissingResourceException e) {
throw new ResourceBundleNotFound(name, locale, classLoader, e);
}
}
public Locale getLocale() {
return locale;
}
@SuppressWarnings("serial")
public static class ResourceBundleNotFound extends RuntimeException {
public static final String PATH_SEPARATOR = ";";
public ResourceBundleNotFound(String bundleName, Locale locale, ClassLoader classLoader,
MissingResourceException cause) {
super("Resource bundle " + bundleName + " not found for locale " + locale + " in classLoader "
+ asString(classLoader), cause);
}
private static String asString(ClassLoader classLoader) {
if (classLoader instanceof URLClassLoader) {
return StringUtils.join(((URLClassLoader)classLoader).getURLs(), PATH_SEPARATOR);
}
return classLoader.toString();
}
}
@SuppressWarnings("serial")
public static class LocalizedKeywordNotFound extends RuntimeException {
public LocalizedKeywordNotFound(String key, String bundleName, Locale locale) {
super("Keyword " + key + " not found for locale " + locale + " in bundle " + bundleName);
}
}
}