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 }