/*
* Copyright 2017 Trimou Team
*
* 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.trimou.spring4.i18n;
import static org.trimou.handlebars.OptionsHashKeys.LOCALE;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.trimou.engine.locale.LocaleSupport;
import org.trimou.handlebars.Options;
import org.trimou.handlebars.OptionsHashKeys;
import org.trimou.handlebars.i18n.LocaleAwareValueHelper;
import org.trimou.util.Arrays;
import org.trimou.util.ImmutableSet;
import org.trimou.util.Strings;
/**
* <p>
* First register the helper instance:
* </p>
* <code>
* MustacheEngineBuilder.newBuilder().registerHelper("msg", new SpringMessageSourceHelper(messageSource)).build();
* </code>
* <p>
* <p>
* Than use the helper in the template:
* </p>
* <code>
* {{msg 'my.key'}}
* </code>
* <p>
* A default message can be set via options hash with {@link SpringMessageSourceHelper#DEFAULT_MESSAGE}.
* <p>
* <code>
* {{msg 'key' defaultMessage='my default message'}}
* </code>
* <p>
* A custom {@link Locale} can be set via options hash with
* {@link OptionsHashKeys#LOCALE} key. See also
* {@link LocaleAwareValueHelper#getLocale(Options)}.
* <p>
* <code>
* {{msg 'key' locale='fr'}}
* </code>
*
* @see LocaleSupport
*/
public final class SpringMessageSourceHelper extends LocaleAwareValueHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringMessageSourceHelper.class);
private static final String DEFAULT_MESSAGE = "defaultMessage";
private final MessageSource messageSource;
/**
* Creates an instance of {@link SpringMessageSourceHelper} with the given {@link MessageSource} instance.
*
* @param messageSource instance of {@link MessageSource} to read messages from
*/
public SpringMessageSourceHelper(final MessageSource messageSource) {
this.messageSource = Objects.requireNonNull(messageSource, "messageSource must not be null");
}
@Override
public void execute(final Options options) {
final String msgCode = options.getParameters().get(0).toString();
final String defaultMessage = getDefaultMessage(options.getHash());
final Locale locale = getLocale(options);
final Object[] msgArguments = getMessageArguments(options.getParameters());
try {
if (Strings.isEmpty(defaultMessage)) {
append(options, messageSource.getMessage(msgCode, msgArguments, locale));
} else {
append(options, messageSource.getMessage(msgCode, msgArguments, defaultMessage, locale));
}
} catch (NoSuchMessageException e) {
LOGGER.warn("Message code {} has not been found", msgCode);
append(options, msgCode);
}
}
@Override
protected Set<String> getSupportedHashKeys() {
return ImmutableSet.of(LOCALE, DEFAULT_MESSAGE);
}
private String getDefaultMessage(final Map<String, Object> hash) {
final Object value = hash.get(DEFAULT_MESSAGE);
return value == null ? null : value.toString();
}
private Object[] getMessageArguments(final List<Object> params) {
if (params.size() > 1) {
return params.subList(1, params.size()).toArray();
}
return Arrays.EMPTY_OBJECT_ARRAY;
}
}