blob: 0ad019eff352c33028a639ede61678e8ea987263 [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.olingo.odata2.core.exception;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingFormatArgumentException;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.apache.olingo.odata2.api.exception.MessageReference;
/**
*
*/
public class MessageService {
private static final String BUNDLE_NAME = "i18n";
private final ResourceBundle resourceBundle;
private final Locale requestedLocale;
private static final Map<Locale, MessageService> LOCALE_2_MESSAGE_SERVICE = new HashMap<Locale, MessageService>();
private MessageService(final Locale locale) {
requestedLocale = locale;
resourceBundle = createResourceBundle(locale);
}
/**
* Create a {@link ResourceBundle} based on given locale and name ({@value #BUNDLE_NAME}).
* If during creation an exception occurs it is catched and an special bundle is created with error type and message
* of
* this exception.
*
* @param locale for which locale the {@link ResourceBundle} is created
* @return a {@link ResourceBundle}
*/
private ResourceBundle createResourceBundle(final Locale locale) {
ResourceBundle bundle;
try {
if (locale == null) {
throw new IllegalArgumentException("Parameter locale MUST NOT be NULL.");
}
bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
} catch (final Exception e) {
bundle = new ResourceBundle() {
@Override
protected Object handleGetObject(final String key) {
return "MessageService could not be created because of exception '" +
e.getClass().getSimpleName() + " with message '" + e.getMessage() + "'.";
}
@Override
public Locale getLocale() {
return Locale.ENGLISH;
}
@SuppressWarnings("unchecked")
@Override
public Enumeration<String> getKeys() {
return (Enumeration<String>) Collections.emptySet();
}
};
}
return bundle;
}
public static class Message {
private final String localizedText;
private final Locale locale;
public Message(final Locale locale, final String localizedMessage) {
super();
localizedText = localizedMessage;
this.locale = locale;
}
public String getText() {
return localizedText;
}
public Locale getLocale() {
return locale;
}
/**
* Get language as defined in RFC 4646 based on {@link Locale}.
*
* @return the language label
*/
public String getLang() {
Locale locale = getLocale();
if (locale.getCountry().isEmpty()) {
return locale.getLanguage();
}
return locale.getLanguage() + "-" + locale.getCountry();
}
}
public static MessageService getInstance(final Locale locale) {
MessageService messagesInstance = LOCALE_2_MESSAGE_SERVICE.get(locale);
if (messagesInstance == null) {
messagesInstance = new MessageService(locale);
LOCALE_2_MESSAGE_SERVICE.put(locale, messagesInstance);
}
return messagesInstance;
}
public static boolean isLocaleSupported(final Locale locale) {
if (locale == null) {
return false;
}
MessageService service = getInstance(locale);
return service.getLocale().equals(locale);
}
/**
* Return first found supported {@link Locale} (iterating over list starting with first element).
* If no {@link Locale} is supported <code>NULL</code> is returned.
*
* @param locales
* @return first supported {@link Locale} or <code>NULL</code>.
*/
public static Locale getSupportedLocale(final List<Locale> locales) {
return getSupportedLocale(locales, null);
}
/**
* Return first found supported {@link Locale} (iterating over list starting with first element).
* If no {@link Locale} is supported given <code>defaultLocale</code> is returned.
*
* @param locales to be checked locales
* @param defaultLocale local which is returned if no supported local is in given <code>locales</code> list
* @return first supported {@link Locale} or given <code>defaultLocale</code>.
*/
public static Locale getSupportedLocale(final List<Locale> locales, final Locale defaultLocale) {
for (Locale locale : locales) {
if (isLocaleSupported(locale)) {
return locale;
}
}
return defaultLocale;
}
public static MessageService getInstance(final List<Locale> locales) {
MessageService service = null;
for (Locale locale : locales) {
service = getInstance(locale);
if (service.getLocale().equals(locale)) {
break;
}
}
return service;
}
public static Message getMessage(final Locale language, final MessageReference context) {
Object[] contentAsArray = context.getContent().toArray(new Object[0]);
return getMessage(language, context.getKey(), contentAsArray);
}
public static Message getMessage(final Locale locale, final String key, final Object... replacements) {
MessageService messages = MessageService.getInstance(locale);
return messages.getMessage(key, replacements);
}
/**
*
* @param key
* @param replacements
* @return the message
*/
private Message getMessage(final String key, final Object... replacements) {
String message = null;
try {
message = resourceBundle.getString(key);
StringBuilder builder = new StringBuilder();
Formatter f = new Formatter(builder, requestedLocale);
f.format(message, replacements);
f.close();
return new Message(getLocale(), builder.toString());
} catch (MissingResourceException e) {
return new Message(Locale.ENGLISH, "Missing message for key '" + key + "'!");
} catch (MissingFormatArgumentException e) {
return new Message(Locale.ENGLISH, "Missing replacement for place holder in message '" + message +
"' for following arguments '" + Arrays.toString(replacements) + "'!");
}
}
public Locale getLocale() {
return resourceBundle.getLocale();
}
public Enumeration<String> getKeys() {
return resourceBundle.getKeys();
}
}