001 /* 002 * Copyright 2011 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 */ 016 package org.kuali.kfs.gl.batch.service.impl; 017 018 import java.io.File; 019 import java.io.InputStream; 020 import java.util.HashSet; 021 import java.util.List; 022 import java.util.Set; 023 024 import org.apache.commons.lang.StringUtils; 025 import org.kuali.kfs.gl.batch.EnterpriseFeedStep; 026 import org.kuali.kfs.gl.batch.service.EnterpriseFeederNotificationService; 027 import org.kuali.kfs.sys.KFSConstants; 028 import org.kuali.kfs.sys.KFSKeyConstants; 029 import org.kuali.kfs.sys.Message; 030 import org.kuali.rice.kns.mail.MailMessage; 031 import org.kuali.rice.kns.service.KualiConfigurationService; 032 import org.kuali.rice.kns.service.MailService; 033 import org.kuali.rice.kns.service.ParameterService; 034 035 /** 036 * The base implementation of EnterpriseFeederNotificationService; performs email-based notifications 037 */ 038 public class EnterpriseFeederNotificationServiceImpl implements EnterpriseFeederNotificationService { 039 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(EnterpriseFeederNotificationServiceImpl.class); 040 041 private ParameterService parameterService; 042 private KualiConfigurationService configurationService; 043 private MailService mailService; 044 045 /** 046 * Performs notification about the status of the upload (i.e. feeding) of a single file set (i.e. done file, data file, and 047 * recon file). 048 * 049 * @param feederProcessName The name of the feeder process; this may correspond to the name of the Spring definition of the 050 * feeder step, but each implementation may define how to use the value of this parameter and/or restrictions on its 051 * value. 052 * @param event The event/status of the upload of the file set 053 * @param doneFile The done file 054 * @param dataFile The data file 055 * @param reconFile The recon file 056 * @param errorMessages Any error messages for which to provide notification 057 * @see org.kuali.kfs.gl.batch.service.EnterpriseFeederNotificationService#notifyFileFeedStatus(java.lang.String, 058 * org.kuali.module.gl.util.EnterpriseFeederEvent, java.io.File, java.io.File, java.io.File, java.util.List) 059 */ 060 public void notifyFileFeedStatus(String feederProcessName, EnterpriseFeederStatus status, File doneFile, File dataFile, File reconFile, List<Message> errorMessages) { 061 String doneFileDescription = doneFile == null ? "Done file missing" : doneFile.getAbsolutePath(); 062 String dataFileDescription = dataFile == null ? "Data file missing" : dataFile.getAbsolutePath(); 063 String reconFileDescription = reconFile == null ? "Recon file missing" : reconFile.getAbsolutePath(); 064 065 // this implementation does not use the contents of the file, so we don't bother opening up the files 066 notifyFileFeedStatus(feederProcessName, status, doneFileDescription, null, dataFileDescription, null, reconFileDescription, null, errorMessages); 067 } 068 069 /** 070 * Performs notifications 071 * 072 * @param feederProcessName The name of the feeder process; this may correspond to the name of the Spring definition of the 073 * feeder step, but each implementation may define how to use the value of this parameter and/or restrictions on its 074 * value. 075 * @param status The event/status of the upload of the file set 076 * @param doneFileDescription The file name 077 * @param doneFileContents Not used; can be set to null 078 * @param dataFileDescription The file name 079 * @param dataFileContents Not used; can be set to null 080 * @param reconFileDescription The file name 081 * @param reconFileContents Not used; can be set to null 082 * @param errorMessages Any error messages for which to provide notification 083 * @see org.kuali.kfs.gl.batch.service.EnterpriseFeederNotificationService#notifyFileFeedStatus(java.lang.String, 084 * org.kuali.module.gl.util.EnterpriseFeederEvent, java.lang.String, java.io.InputStream, java.lang.String, 085 * java.io.InputStream, java.lang.String, java.io.InputStream, java.util.List) 086 */ 087 public void notifyFileFeedStatus(String feederProcessName, EnterpriseFeederStatus status, String doneFileDescription, InputStream doneFileContents, String dataFileDescription, InputStream dataFileContents, String reconFileDescription, InputStream reconFileContents, List<Message> errorMessages) { 088 try { 089 if (isStatusNotifiable(feederProcessName, status, doneFileDescription, dataFileDescription, reconFileDescription, errorMessages)) { 090 Set<String> toEmailAddresses = generateToEmailAddresses(feederProcessName, status, doneFileDescription, dataFileDescription, reconFileDescription, errorMessages); 091 String fromEmailAddress = mailService.getBatchMailingList(); 092 093 MailMessage mailMessage = new MailMessage(); 094 mailMessage.setFromAddress(fromEmailAddress); 095 mailMessage.setToAddresses(toEmailAddresses); 096 mailMessage.setSubject(getSubjectLine(doneFileDescription, dataFileDescription, reconFileDescription, errorMessages, feederProcessName, status)); 097 mailMessage.setMessage(buildFileFeedStatusMessage(doneFileDescription, dataFileDescription, reconFileDescription, errorMessages, feederProcessName, status)); 098 099 mailService.sendMessage(mailMessage); 100 } 101 } 102 catch (Exception e) { 103 // Have to try to prevent notification exceptions from breaking control flow in the caller 104 // log and swallow the exception 105 LOG.error("Error occured trying to send notifications.", e); 106 } 107 } 108 109 /** 110 * Generates the destination address(s) for the email notifications, possibly depending on the parameter values 111 * 112 * @param feederProcessName The name of the feeder process; this may correspond to the name of the Spring definition of the 113 * feeder step, but each implementation may define how to use the value of this parameter and/or restrictions on its 114 * value. 115 * @param status The event/status of the upload of the file set 116 * @param doneFileDescription The file name 117 * @param dataFileDescription The file name 118 * @param reconFileDescription The file name 119 * @param errorMessages Any error messages for which to provide notification 120 * @return the destination addresses 121 */ 122 protected Set<String> generateToEmailAddresses(String feederProcessName, EnterpriseFeederStatus status, String doneFileDescription, String dataFileDescription, String reconFileDescription, List<Message> errorMessages) { 123 Set<String> addresses = new HashSet<String>(); 124 String[] addressesArray = parameterService.getParameterValues(EnterpriseFeedStep.class, KFSConstants.EnterpriseFeederApplicationParameterKeys.TO_ADDRESS).toArray(new String[] {}); 125 for (String address : addressesArray) { 126 addresses.add(address); 127 } 128 return addresses; 129 } 130 131 /** 132 * Generates the "From:" address for the email 133 * 134 * @param feederProcessName The name of the feeder process; this may correspond to the name of the Spring definition of the 135 * feeder step, but each implementation may define how to use the value of this parameter and/or restrictions on its 136 * value. 137 * @param status The event/status of the upload of the file set 138 * @param doneFileDescription The file name 139 * @param dataFileDescription The file name 140 * @param reconFileDescription The file name 141 * @param errorMessages Any error messages for which to provide notification 142 * @return the source address 143 */ 144 protected String generateFromEmailAddress(String feederProcessName, EnterpriseFeederStatus status, String doneFileDescription, String dataFileDescription, String reconFileDescription, List<Message> errorMessages) { 145 return mailService.getBatchMailingList(); 146 } 147 148 /** 149 * Generates the status message that would be generated by a call to notifyFileFeedStatus with the same parameters. 150 * 151 * @param feederProcessName The name of the feeder process; this may correspond to the name of the Spring definition of the 152 * feeder step, but each implementation may define how to use the value of this parameter and/or restrictions on its 153 * value. 154 * @param event The event/status of the upload of the file set 155 * @param doneFile The done file 156 * @param dataFile The data file 157 * @param reconFile The recon file 158 * @param errorMessages Any error messages for which to provide notification 159 * @see org.kuali.kfs.gl.batch.service.EnterpriseFeederNotificationService#getFileFeedStatusMessage(java.lang.String, 160 * org.kuali.module.gl.util.EnterpriseFeederEvent, java.io.File, java.io.File, java.io.File, java.util.List) 161 */ 162 public String getFileFeedStatusMessage(String feederProcessName, EnterpriseFeederStatus status, File doneFile, File dataFile, File reconFile, List<Message> errorMessages) { 163 String doneFileDescription = doneFile.getAbsolutePath(); 164 String dataFileDescription = dataFile.getAbsolutePath(); 165 String reconFileDescription = reconFile.getAbsolutePath(); 166 167 return buildFileFeedStatusMessage(doneFileDescription, dataFileDescription, reconFileDescription, errorMessages, feederProcessName, status); 168 } 169 170 /** 171 * @see org.kuali.kfs.gl.batch.service.EnterpriseFeederNotificationService#getFileFeedStatusMessage(java.lang.String, 172 * org.kuali.module.gl.util.EnterpriseFeederEvent, java.lang.String, java.io.InputStream, java.lang.String, 173 * java.io.InputStream, java.lang.String, java.io.InputStream, java.util.List) 174 */ 175 public String getFileFeedStatusMessage(String feederProcessName, EnterpriseFeederStatus status, String doneFileDescription, InputStream doneFileContents, String dataFileDescription, InputStream dataFileContents, String reconFileDescription, InputStream reconFileContents, List<Message> errorMessages) { 176 return buildFileFeedStatusMessage(doneFileDescription, dataFileDescription, reconFileDescription, errorMessages, feederProcessName, status); 177 } 178 179 /** 180 * Builds the status message for the status of a feed. 181 * 182 * @param doneFileDescription the name of the done file 183 * @param dataFileDescription the name of the file to read data from 184 * @param reconFileDescription the name of the reconciliation file 185 * @param errorMessages a List of error messages 186 * @param feederProcessName the name of the feeder process 187 * @return the String of the subject line 188 */ 189 protected String getSubjectLine(String doneFileDescription, String dataFileDescription, String reconFileDescription, List<Message> errorMessages, String feederProcessName, EnterpriseFeederStatus status) { 190 String subject = configurationService.getPropertyString(KFSKeyConstants.ERROR_ENTERPRISE_FEEDER_RECONCILIATION_OR_LOADING_ERROR); 191 if (subject == null) { 192 return "ERROR in reconciling or loading GL origin entries from file."; 193 } 194 String productionEnvironmentCode = configurationService.getPropertyString(KFSConstants.PROD_ENVIRONMENT_CODE_KEY); 195 String environmentCode = configurationService.getPropertyString(KFSConstants.ENVIRONMENT_KEY); 196 if (!StringUtils.equals(productionEnvironmentCode, environmentCode)) { 197 subject = environmentCode + ": " + subject; 198 } 199 return subject; 200 } 201 202 /** 203 * Builds the status message for the status of a feed. 204 * 205 * @param doneFileName the name of the done file 206 * @param dataFileName the name of the file to get data from 207 * @param reconFileName the reconciliation file 208 * @param errorMessages a List of error messages generated during the process 209 * @param feederProcessName the name of the feeder process 210 * @return a String with the status message 211 */ 212 protected String buildFileFeedStatusMessage(String doneFileName, String dataFileName, String reconFileName, List<Message> errorMessages, String feederProcessName, EnterpriseFeederStatus status) { 213 StringBuilder buf = new StringBuilder(); 214 215 buf.append("Data file: ").append(dataFileName).append("\n"); 216 buf.append("Reconciliation File: ").append(reconFileName).append("\n"); 217 buf.append("Done file: ").append(doneFileName).append("\n\n\n"); 218 219 buf.append("Status: ").append(status.getStatusDescription()).append("\n\n\n"); 220 221 if (status.isErrorEvent()) { 222 buf.append("The done file has been removed and "); 223 if (StringUtils.isNotBlank(feederProcessName)) { 224 buf.append(feederProcessName); 225 } 226 else { 227 buf.append("<process name unavailable>"); 228 } 229 buf.append(" will continue without processing this set of files (see below)."); 230 231 buf.append(" Please correct and resend the files for the next day's batch."); 232 } 233 234 buf.append("\n\n"); 235 236 if (!errorMessages.isEmpty()) { 237 buf.append("Error/warning messages:\n"); 238 for (Message message : errorMessages) { 239 if (message.getType() == Message.TYPE_FATAL) { 240 buf.append("ERROR: "); 241 } 242 if (message.getType() == Message.TYPE_WARNING) { 243 buf.append("WARNING: "); 244 } 245 buf.append(message.getMessage()).append("\n"); 246 } 247 } 248 249 return buf.toString(); 250 } 251 252 /** 253 * Returns whether a notification is necessary given the values of the parameters 254 * 255 * @param feederProcessName the name of the process that invoked the feeder 256 * @param status the status of the feed 257 * @param doneFileDescription the done file description 258 * @param dataFileDescription the data file description 259 * @param reconFileDescription the recon file description 260 * @param errorMessages a list of error messages 261 * @return whether to notify 262 */ 263 protected boolean isStatusNotifiable(String feederProcessName, EnterpriseFeederStatus status, String doneFileDescription, String dataFileDescription, String reconFileDescription, List<Message> errorMessages) { 264 if (status instanceof FileReconOkLoadOkStatus) { 265 return false; 266 } 267 return true; 268 } 269 270 271 /** 272 * Sets the mailService attribute value. 273 * 274 * @param mailService The mailService to set. 275 */ 276 public void setMailService(MailService mailService) { 277 this.mailService = mailService; 278 } 279 280 public void setConfigurationService(KualiConfigurationService configurationService) { 281 this.configurationService = configurationService; 282 } 283 284 public void setParameterService(ParameterService parameterService) { 285 this.parameterService = parameterService; 286 } 287 }