/*
* JSmart Framework - Java Web Development Framework
* Copyright (c) 2015, Jeferson Albino da Silva, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jsmartframework.web.util;
import static com.jsmartframework.web.config.Config.CONFIG;
import com.jsmartframework.web.manager.WebContext;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
/**
* This class represents the container of text resources mapped on configuration file
* based on the different {@link Locale} mapped for those resources.
* <br>
* Each text properties file is mapped as resource in this container according to what
* was mapped on configuration via {@code webConfig.xml}.
*/
public enum WebText {
TEXTS();
public static final String NOT_FOUND = "???";
private static final Logger LOGGER = Logger.getLogger(WebText.class.getPackage().getName());
private static final Pattern BRACKETS = Pattern.compile(".*\\{[0-9]*\\}.*");
private final WebTextControl control = new WebTextControl();
private static Locale defaultLocale;
private Set<String> resources = new HashSet<>();
public void init() {
String[] messageFiles = CONFIG.getContent().getMessageFiles();
if (messageFiles != null) {
for (String msg : messageFiles) {
resources.add(msg);
}
}
String defaultLanguage = CONFIG.getContent().getDefaultLanguage();
if (defaultLanguage != null) {
defaultLocale = new Locale(defaultLanguage);
}
}
public static WebTextSet getStrings(String res, String keyPrefix, String language) {
if (!containsResource(res)) {
LOGGER.log(Level.SEVERE, "Resource " + res + " not found to return set of messages!");
return null;
}
Locale locale;
if (language != null) {
locale = new Locale(language);
} else {
locale = defaultLocale != null ? defaultLocale : Locale.getDefault();
}
WebTextSet webTextSet = new WebTextSet(locale);
ResourceBundle bundle = getBundle(res, locale);
for (String key : bundle.keySet()) {
if (key.startsWith(keyPrefix)) {
webTextSet.putValue(key, bundle.getString(key));
}
}
return webTextSet;
}
/**
* Return <code>true</code> if some resource mapped on configuration file is
* presented on this container, <code>false</code> otherwise.
*
* @param res resource name mapped on configuration file.
* @return boolean indicating the presence of specified resource.
*/
public static boolean containsResource(String res) {
return TEXTS.resources.contains(res);
}
/**
* Returns the string mapped by specified resource and key inside the file according
* to the standard of properties file.
* <br>
* The string returned considers the {@link Locale} of the current request being processed.
*
* @param res resource name mapped on configuration file.
* @param key key of the string inside the properties file
* @return the string on resource file according to the {@link Locale} of the request.
*/
public static String getString(String res, String key) {
try {
if (!containsResource(res)) {
LOGGER.log(Level.INFO, "Resource " + res + " not found!");
return NOT_FOUND;
}
Locale locale = WebContext.getLocale();
if (locale == null) {
locale = defaultLocale != null ? defaultLocale : Locale.getDefault();
}
return getBundle(res, locale).getString(key);
} catch (MissingResourceException ex) {
LOGGER.log(Level.INFO, "Message for " + key + " not found: " + ex.getMessage());
}
return NOT_FOUND;
}
private static ResourceBundle getBundle(String res, String language) {
return getBundle(res, new Locale(language));
}
private static ResourceBundle getBundle(String res, Locale locale) {
return ResourceBundle.getBundle(res, locale, TEXTS.control);
}
public static String getString(String res, String key, Object ... params) {
String string = getString(res, key);
string = formatString(string, params);
return string;
}
public static String formatString(String string, Object ... params) {
if (string != null && params != null && params.length > 0) {
if (BRACKETS.matcher(string).find()) {
string = MessageFormat.format(string, params);
} else if (string.contains("%s")) {
string = String.format(string, params);
}
}
return string;
}
private class WebTextControl extends ResourceBundle.Control {
@Override
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
List<Locale> locales = super.getCandidateLocales(baseName, locale);
if (defaultLocale != null) {
locales.add(locales.indexOf(Locale.ROOT), defaultLocale);
}
return locales;
}
}
public static class WebTextSet {
private final String language;
private final Map<String, Object> values = new HashMap<>();
private WebTextSet(Locale locale) {
this.language = locale.getLanguage();
}
public String getLanguage() {
return language;
}
private void putValue(String key, Object value) {
values.put(key, value);
}
public Map<String, Object> getValues() {
return values;
}
}
}