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