View Javadoc
1   /**
2    * Copyright 2005-2015 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  
37      private LookupService lookupService;
38  
39      /**
40       * @see org.kuali.rice.krad.messages.MessageProvider#getMessage(java.lang.String, java.lang.String,
41       * java.lang.String, java.lang.String)
42       */
43      public Message getMessage(String namespace, String component, String key, String locale) {
44          Collection<Message> results = getMessageByCriteria(namespace, component, key, locale);
45  
46          if ((results != null) && !results.isEmpty()) {
47              return results.iterator().next();
48          }
49  
50          return null;
51      }
52  
53      /**
54       * @see org.kuali.rice.krad.messages.MessageProvider#getAllMessagesForComponent(java.lang.String,
55       * java.lang.String, java.lang.String)
56       */
57      public Collection<Message> getAllMessagesForComponent(String namespace, String component, String locale) {
58          return getMessageByCriteria(namespace, component, null, locale);
59      }
60  
61      /**
62       * Performs a query using the {@link LookupService} to retrieve messages that match the given
63       * namespace, component, name, and locale. Not parameters maybe empty in which case they will not be added
64       * to the criteria
65       *
66       * @param namespace namespace code to search for
67       * @param component component code to search for
68       * @param key key of the parameter to find
69       * @param locale locale code to search for
70       * @return Collection<Message> matching messages or empty collection if not are found
71       */
72      protected Collection<Message> getMessageByCriteria(String namespace, String component, String key, String locale) {
73          Collection<Message> results = null;
74  
75          Map<String, String> criteria = new HashMap<String, String>();
76  
77          if (StringUtils.isNotBlank(namespace)) {
78              criteria.put("namespaceCode", namespace);
79          }
80  
81          if (StringUtils.isNotBlank(component)) {
82              criteria.put("componentCode", component);
83          }
84  
85          if (StringUtils.isNotBlank(key)) {
86              criteria.put("key", key);
87          }
88  
89          if (StringUtils.isNotBlank(locale)) {
90              // build or condition that will match just the language as well
91              String[] localeIdentifiers = StringUtils.split(locale, "-");
92              if ((localeIdentifiers == null) || (localeIdentifiers.length != 2)) {
93                  throw new RiceRuntimeException("Invalid locale code: " + (locale == null ? "Null" : locale));
94              }
95  
96              String localeLanguage = localeIdentifiers[0];
97              if ( StringUtils.isNotBlank(localeLanguage)) {
98                  criteria.put("locale", locale + SearchOperator.OR.op() + localeLanguage);
99              } else {
100                 criteria.put("locale", locale );
101             }
102         }
103 
104         results = getLookupService().findCollectionBySearch(Message.class, criteria);
105 
106         // filter out duplicate message results due to locale wildcard search (for example could have a match 
107         // for en and en-US, in which case we want to take the record for the more specific locale
108         Map<String, Message> uniqueMessages = new HashMap<String, Message>();
109         for (Message message : results) {
110             String messageKey = message.getNamespaceCode() + "|" + message.getComponentCode() + "|" + message.getKey();
111             if (uniqueMessages.containsKey(messageKey)) {
112                 Message duplicateMessage = uniqueMessages.get(messageKey);
113                 // attempt to find the one that matches the locale exactly
114                 if (message.getLocale().equals(locale)) {
115                     // use current message, otherwise leave the previous message
116                     uniqueMessages.put(messageKey, message);
117                 }
118             } else {
119                 uniqueMessages.put(messageKey, message);
120             }
121         }
122 
123         return uniqueMessages.values();
124     }
125 
126     public LookupService getLookupService() {
127         if (lookupService == null) {
128             lookupService = KRADServiceLocatorWeb.getLookupService();
129         }
130 
131         return lookupService;
132     }
133 
134     public void setLookupService(LookupService lookupService) {
135         this.lookupService = lookupService;
136     }
137 
138 }