001/**
002 * Copyright 2005-2018 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.messages;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
020import org.kuali.rice.krad.util.KRADConstants;
021
022import java.util.ArrayList;
023import java.util.Collection;
024import java.util.List;
025
026/**
027 * Implementation of the {@link MessageService} that allows {@link MessageProvider} implementations
028 * to be configured for exposing external message repositories
029 *
030 * <p>
031 * This message service implementation essentially delegates all calls down to one or more message
032 * providers. When more than one message provider is configured, providers higher up in the chain will
033 * receive priority. That is, when finding a message the first provider that has the message will be used
034 * and no others will be consulted. When finding a collection of messages, if the same message (key) exists
035 * from more than one provider, the message from the first encountered provider (in the List) will
036 * be used.
037 * </p>
038 *
039 * <p>
040 * The default namespace and component are constants of the service implementation and may not be changed.
041 * </p>
042 *
043 * @author Kuali Rice Team (rice.collab@kuali.org)
044 */
045public class MessageServiceImpl implements MessageService {
046    private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MessageServiceImpl.class);
047
048    private List<MessageProvider> messageProviders;
049
050    /**
051     * @see MessageService#getMessage(java.lang.String, java.lang.String, java.lang.String)
052     */
053    public Message getMessage(String namespace, String component, String key) {
054        return getMessage(namespace, component, key, getDefaultLocaleCode());
055    }
056
057    /**
058     * @see MessageService#getMessage(java.lang.String, java.lang.String, java.lang.String)
059     */
060    public Message getMessage(String namespace, String component, String key, String locale) {
061        Message message = null;
062
063        // use default namespace and component if not given
064        if (StringUtils.isBlank(namespace)) {
065            namespace = DEFAULT_NAMESPACE_CODE;
066        }
067
068        if (StringUtils.isBlank(component)) {
069            component = DEFAULT_COMPONENT_CODE;
070        }
071
072        if (StringUtils.isBlank(locale)) {
073            locale = getDefaultLocaleCode();
074        }
075
076        for (MessageProvider provider : messageProviders) {
077            message = provider.getMessage(namespace, component, key, locale);
078
079            if (message != null) {
080                // don't check with any additional providers
081                break;
082            }
083        }
084
085        return message;
086    }
087
088    /**
089     * @see MessageService#getMessageText(java.lang.String, java.lang.String, java.lang.String)
090     */
091    public String getMessageText(String namespace, String component, String key) {
092        return getMessageText(namespace, component, key, getDefaultLocaleCode());
093    }
094
095    /**
096     * @see MessageService#getMessageText(java.lang.String, java.lang.String, java.lang.String)
097     */
098    public String getMessageText(String namespace, String component, String key, String locale) {
099        Message message = getMessage(namespace, component, key, locale);
100        if (message != null) {
101            return message.getText();
102        }
103
104        return null;
105    }
106
107    /**
108     * @see MessageService#getMessageText(java.lang.String, java.lang.String, java.lang.String)
109     */
110    public String getMessageText(String key) {
111        return getMessageText(key, getDefaultLocaleCode());
112    }
113
114    /**
115     * @see MessageService#getMessageText(java.lang.String, java.lang.String, java.lang.String)
116     */
117    public String getMessageText(String key, String locale) {
118        Message message = getMessage(null, null, key, locale);
119        if (message != null) {
120            return message.getText();
121        }
122
123        return null;
124    }
125
126    /**
127     * @see MessageService#getAllMessagesForComponent(java.lang.String, java.lang.String)
128     */
129    public Collection<Message> getAllMessagesForComponent(String namespace, String component) {
130        return getAllMessagesForComponent(namespace, component, getDefaultLocaleCode());
131    }
132
133    /**
134     * @see MessageService#getAllMessagesForComponent(java.lang.String, java.lang.String)
135     */
136    public Collection<Message> getAllMessagesForComponent(String namespace, String component, String locale) {
137        Collection<Message> messages = new ArrayList<Message>();
138
139        if (StringUtils.isBlank(locale)) {
140            locale = getDefaultLocaleCode();
141        }
142
143        for (MessageProvider provider : messageProviders) {
144            Collection<Message> providerMessages = provider.getAllMessagesForComponent(namespace, component, locale);
145            mergeMessages(messages, providerMessages);
146        }
147
148        return messages;
149    }
150
151    /**
152     * Merges the second collection into the first collection
153     *
154     * <p>
155     * If a message with the same key (namespace, component, and name) is found in both collections, the message
156     * from first collection will remain. That is, the message in the second collection will NOT override
157     * </p>
158     *
159     * @param messages collection to be merged into
160     * @param messagesToMerge collection that will be merged with first
161     */
162    protected void mergeMessages(Collection<Message> messages, Collection<Message> messagesToMerge) {
163        for (Message message : messagesToMerge) {
164            if (!messages.contains(message)) {
165                messages.add(message);
166            }
167        }
168    }
169
170    /**
171     * Retrieves the default locale code configured through a system parameter
172     *
173     * @return String configured default locale
174     */
175    protected String getDefaultLocaleCode() {
176        String localeCode = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(
177                KRADConstants.KNS_NAMESPACE, KRADConstants.DetailTypes.ALL_DETAIL_TYPE,
178                KRADConstants.ParameterNames.DEFAULT_LOCALE_CODE);
179
180        // if not configured fall back to english US
181        if (StringUtils.isBlank(localeCode)) {
182            localeCode = "en-US";
183        }
184
185        return localeCode;
186    }
187
188    /**
189     * Retrieves the collection of message providers configured with the message service
190     *
191     * @return List<MessageProvider> message provider implementations
192     */
193    protected List<MessageProvider> getMessageProviders() {
194        return messageProviders;
195    }
196
197    /**
198     * Setter for the collection of message providers that should be used by the message service
199     * implementation
200     *
201     * @param messageProviders
202     */
203    public void setMessageProviders(List<MessageProvider> messageProviders) {
204        this.messageProviders = messageProviders;
205    }
206}