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