View Javadoc

1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.messages.providers;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.exception.RiceRuntimeException;
20  import org.kuali.rice.core.api.search.SearchOperator;
21  import org.kuali.rice.krad.messages.Message;
22  import org.kuali.rice.krad.messages.MessageProvider;
23  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
24  import org.kuali.rice.krad.service.LookupService;
25  
26  import java.util.Collection;
27  import java.util.HashMap;
28  import java.util.Map;
29  
30  /**
31   * Implementation of {@link MessageProvider} that stores messages in a database
32   *
33   * @author Kuali Rice Team (rice.collab@kuali.org)
34   */
35  public class DatabaseMessageProvider implements MessageProvider {
36      private LookupService lookupService;
37  
38      /**
39       * @see org.kuali.rice.krad.messages.MessageProvider#getMessage(java.lang.String, java.lang.String,
40       * java.lang.String, java.lang.String)
41       */
42      public Message getMessage(String namespace, String component, String key, String locale) {
43          Collection<Message> results = getMessageByCriteria(namespace, component, key, locale);
44  
45          if ((results != null) && !results.isEmpty()) {
46              return results.iterator().next();
47          }
48  
49          return null;
50      }
51  
52      /**
53       * @see org.kuali.rice.krad.messages.MessageProvider#getAllMessagesForComponent(java.lang.String,
54       * java.lang.String, java.lang.String)
55       */
56      public Collection<Message> getAllMessagesForComponent(String namespace, String component, String locale) {
57          return getMessageByCriteria(namespace, component, null, locale);
58      }
59  
60      /**
61       * Performs a query using the {@link LookupService} to retrieve messages that match the given
62       * namespace, component, name, and locale. Not parameters maybe empty in which case they will not be added
63       * to the criteria
64       *
65       * @param namespace namespace code to search for
66       * @param component component code to search for
67       * @param key key of the parameter to find
68       * @param locale locale code to search for
69       * @return Collection<Message> matching messages or empty collection if not are found
70       */
71      protected Collection<Message> getMessageByCriteria(String namespace, String component, String key, String locale) {
72          Collection<Message> results = null;
73  
74          Map<String, String> criteria = new HashMap<String, String>();
75  
76          if (StringUtils.isNotBlank(namespace)) {
77              criteria.put("namespaceCode", namespace);
78          }
79  
80          if (StringUtils.isNotBlank(component)) {
81              criteria.put("componentCode", component);
82          }
83  
84          if (StringUtils.isNotBlank(key)) {
85              criteria.put("key", key);
86          }
87  
88          if (StringUtils.isNotBlank(locale)) {
89              // build or condition that will match just the language as well
90              String[] localeIdentifiers = StringUtils.split(locale, "-");
91              if ((localeIdentifiers == null) || (localeIdentifiers.length != 2)) {
92                  throw new RiceRuntimeException("Invalid locale code: " + (locale == null ? "Null" : locale));
93              }
94  
95              String localeLanguage = localeIdentifiers[0];
96              criteria.put("locale", locale + SearchOperator.OR.op() + localeLanguage);
97          }
98  
99          results = getLookupService().findCollectionBySearch(Message.class, criteria);
100 
101         // filter out duplicate message results due to locale wildcard search (for example could have a match 
102         // for en and en-US, in which case we want to take the record for the more specific locale
103         Map<String, Message> uniqueMessages = new HashMap<String, Message>();
104         for (Message message : results) {
105             String messageKey = message.getNamespaceCode() + "|" + message.getComponentCode() + "|" + message.getKey();
106             if (uniqueMessages.containsKey(messageKey)) {
107                 Message duplicateMessage = uniqueMessages.get(messageKey);
108                 // attempt to find the one that matches the locale exactly
109                 if (message.getLocale().equals(locale)) {
110                     // use current message, otherwise leave the previous message
111                     uniqueMessages.put(messageKey, message);
112                 }
113             } else {
114                 uniqueMessages.put(messageKey, message);
115             }
116         }
117 
118         return uniqueMessages.values();
119     }
120 
121     public LookupService getLookupService() {
122         if (lookupService == null) {
123             lookupService = KRADServiceLocatorWeb.getLookupService();
124         }
125 
126         return lookupService;
127     }
128 
129     public void setLookupService(LookupService lookupService) {
130         this.lookupService = lookupService;
131     }
132 }