001/** 002 * Copyright 2005-2016 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.providers; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.core.api.exception.RiceRuntimeException; 020import org.kuali.rice.core.api.search.SearchOperator; 021import org.kuali.rice.krad.messages.Message; 022import org.kuali.rice.krad.messages.MessageProvider; 023import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 024import org.kuali.rice.krad.service.LookupService; 025 026import java.util.Collection; 027import java.util.HashMap; 028import java.util.Map; 029 030/** 031 * Implementation of {@link MessageProvider} that stores messages in a database 032 * 033 * @author Kuali Rice Team (rice.collab@kuali.org) 034 */ 035public class DatabaseMessageProvider implements MessageProvider { 036 private LookupService lookupService; 037 038 /** 039 * @see org.kuali.rice.krad.messages.MessageProvider#getMessage(java.lang.String, java.lang.String, 040 * java.lang.String, java.lang.String) 041 */ 042 public Message getMessage(String namespace, String component, String key, String locale) { 043 Collection<Message> results = getMessageByCriteria(namespace, component, key, locale); 044 045 if ((results != null) && !results.isEmpty()) { 046 return results.iterator().next(); 047 } 048 049 return null; 050 } 051 052 /** 053 * @see org.kuali.rice.krad.messages.MessageProvider#getAllMessagesForComponent(java.lang.String, 054 * java.lang.String, java.lang.String) 055 */ 056 public Collection<Message> getAllMessagesForComponent(String namespace, String component, String locale) { 057 return getMessageByCriteria(namespace, component, null, locale); 058 } 059 060 /** 061 * Performs a query using the {@link LookupService} to retrieve messages that match the given 062 * namespace, component, name, and locale. Not parameters maybe empty in which case they will not be added 063 * to the criteria 064 * 065 * @param namespace namespace code to search for 066 * @param component component code to search for 067 * @param key key of the parameter to find 068 * @param locale locale code to search for 069 * @return Collection<Message> matching messages or empty collection if not are found 070 */ 071 protected Collection<Message> getMessageByCriteria(String namespace, String component, String key, String locale) { 072 Collection<Message> results = null; 073 074 Map<String, String> criteria = new HashMap<String, String>(); 075 076 if (StringUtils.isNotBlank(namespace)) { 077 criteria.put("namespaceCode", namespace); 078 } 079 080 if (StringUtils.isNotBlank(component)) { 081 criteria.put("componentCode", component); 082 } 083 084 if (StringUtils.isNotBlank(key)) { 085 criteria.put("key", key); 086 } 087 088 if (StringUtils.isNotBlank(locale)) { 089 // build or condition that will match just the language as well 090 String[] localeIdentifiers = StringUtils.split(locale, "-"); 091 if ((localeIdentifiers == null) || (localeIdentifiers.length != 2)) { 092 throw new RiceRuntimeException("Invalid locale code: " + (locale == null ? "Null" : locale)); 093 } 094 095 String localeLanguage = localeIdentifiers[0]; 096 criteria.put("locale", locale + SearchOperator.OR.op() + localeLanguage); 097 } 098 099 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}