/*
* Copyright 2008-2014 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kaleidofoundry.core.i18n;
import static org.kaleidofoundry.core.i18n.I18nConstants.I18nDefaultMessageBundlePluginName;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.Enumeration;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
import org.kaleidofoundry.core.cache.Cache;
import org.kaleidofoundry.core.cache.CacheManager;
import org.kaleidofoundry.core.cache.CacheManagerFactory;
import org.kaleidofoundry.core.context.RuntimeContext;
import org.kaleidofoundry.core.plugin.Declare;
import org.kaleidofoundry.core.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default message bundle implementation
*
* @author jraduget
*/
@Declare(I18nDefaultMessageBundlePluginName)
public class DefaultMessageBundle extends ResourceBundle implements I18nMessages {
static final Logger LOGGER = LoggerFactory.getLogger(DefaultMessageBundle.class);
// used for user resource bundle data
final Cache<String, String> resourceBundleCache;
// used internally for kaleidofoundry internal resource bundle data
final Properties resourceBundleNoCache;
// bundle resource name
final String resourceName;
// bundle parent (can be null)
private ResourceBundle parent;
// internal runtime context
private final RuntimeContext<I18nMessages> context;
/**
* @param resourceName
* @param properties
*/
public DefaultMessageBundle(final String resourceName, final Properties properties) {
this(resourceName, properties, new RuntimeContext<I18nMessages>(I18nMessages.class));
}
/**
* @param resourceName
* @param properties
* @param runtimeContext
*/
public DefaultMessageBundle(final String resourceName, final Properties properties, final RuntimeContext<I18nMessages> runtimeContext) {
context = runtimeContext;
// internal kaleidofoundry resource bundle, does not use internal cache
if (InternalBundleEnum.isInternalBundle(resourceName)) {
LOGGER.debug("Create message bundle with no cache provider for '{}'", resourceName);
resourceBundleNoCache = properties;
resourceBundleCache = null;
}
// user resource bundle, does use internal cache
else {
LOGGER.debug("Create message bundle with cache provider for '{}'", resourceName);
final CacheManager cacheManager;
final String cacheManagerContextRef = context.getString(I18nContextBuilder.CacheManagerRef);
if (!StringHelper.isEmpty(cacheManagerContextRef)) {
cacheManager = CacheManagerFactory.provides(new RuntimeContext<CacheManager>(cacheManagerContextRef, CacheManager.class, context));
} else {
cacheManager = CacheManagerFactory.provides();
}
resourceBundleCache = cacheManager.getCache(resourceName.startsWith("i18n/") ? "kaleidofoundry/" + resourceName : "kaleidofoundry/i18n/"
+ resourceName);
resourceBundleNoCache = null;
// copy common properties to internal Cache<String,String> storage
for (final String propName : properties.stringPropertyNames()) {
resourceBundleCache.put(propName, properties.getProperty(propName));
}
}
this.resourceName = resourceName;
}
/**
* don't use it,
* this constructor is only needed and used by some IOC framework like spring.
*/
DefaultMessageBundle() {
resourceName = null;
context = null;
resourceBundleCache = null;
resourceBundleNoCache = null;
}
/*
* (non-Javadoc)
* @see java.util.ResourceBundle#handleGetObject(java.lang.String)
*/
@Override
protected Object handleGetObject(final String key) {
return resourceBundleCache != null ? resourceBundleCache.get(key) : resourceBundleNoCache.getProperty(key);
}
/*
* (non-Javadoc)
* @see java.util.ResourceBundle#getKeys()
*/
@Override
public Enumeration<String> getKeys() {
final Set<String> handleKeys = resourceBundleCache != null ? resourceBundleCache.keys() : resourceBundleNoCache.stringPropertyNames();
return Collections.enumeration(handleKeys);
}
/*
* (non-Javadoc)
* @see org.kaleidofoundry.core.i18n.I18nMessages#getMessage(java.lang.String)
*/
@Override
public String getMessage(final String key) throws MissingResourceException {
return getMessage(key, (Object[]) null);
}
/*
* (non-Javadoc)
* @see org.kaleidofoundry.core.i18n.I18nMessages#getMessage(java.lang.String, java.lang.Object[])
*/
@Override
public String getMessage(final String key, final Object... array) throws MissingResourceException {
String msg = null;
try {
msg = getString(key);
} catch (MissingResourceException mre) {
}
if (msg == null) {
// it can't be an i18n message, where are inside the bundle currently instantiate
throw new MissingResourceException("Cannot find message key '" + key + "' in resource '" + resourceName + "'", DefaultMessageBundle.class.getName(), key);
}
// with locale specifics
return (new MessageFormat(msg, getLocale())).format(array, new StringBuffer(), null).toString();
// return MessageFormat.format(msg, array);
}
/*
* (non-Javadoc)
* @see org.kaleidofoundry.core.i18n.MessageBundle#getParent()
*/
@Override
public ResourceBundle getParent() {
return parent;
}
/*
* (non-Javadoc)
* @see java.util.ResourceBundle#setParent(java.util.ResourceBundle)
*/
@Override
public void setParent(final ResourceBundle parent) {
this.parent = parent;
super.setParent(parent);
}
/*
* (non-Javadoc)
* @see org.kaleidofoundry.core.i18n.MessageBundle#getResourceName()
*/
@Override
public String getResourceName() {
return resourceName;
}
}