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.module.cam.report;
017    
018    import java.io.File;
019    import java.io.FileOutputStream;
020    import java.text.SimpleDateFormat;
021    import java.util.Date;
022    import java.util.List;
023    
024    import org.kuali.kfs.module.cam.CamsConstants;
025    import org.kuali.kfs.module.cam.CamsKeyConstants;
026    import org.kuali.kfs.sys.KFSConstants;
027    import org.kuali.kfs.sys.context.SpringContext;
028    import org.kuali.rice.kns.service.DateTimeService;
029    import org.kuali.rice.kns.service.KualiConfigurationService;
030    
031    import com.lowagie.text.Cell;
032    import com.lowagie.text.Chunk;
033    import com.lowagie.text.Document;
034    import com.lowagie.text.DocumentException;
035    import com.lowagie.text.Element;
036    import com.lowagie.text.ExceptionConverter;
037    import com.lowagie.text.Font;
038    import com.lowagie.text.FontFactory;
039    import com.lowagie.text.Paragraph;
040    import com.lowagie.text.Phrase;
041    import com.lowagie.text.Rectangle;
042    import com.lowagie.text.Table;
043    import com.lowagie.text.pdf.PdfPCell;
044    import com.lowagie.text.pdf.PdfPTable;
045    import com.lowagie.text.pdf.PdfPageEventHelper;
046    import com.lowagie.text.pdf.PdfWriter;
047    
048    public class DepreciationReport {
049    
050    
051        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DepreciationReport.class);
052        private int pageNumber = 0;
053        private int line = 0;
054        private int linesPerPage = 28;
055        private Document document;
056        private PdfWriter writer;
057    
058        /**
059         * This method creates the report file and invokes the methods that write the data
060         * 
061         * @param reportLog
062         * @param errorMsg
063         */
064        public void generateReport(List<String[]> reportLog, String errorMsg, String sDepreciationDate) {
065            try {
066                DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
067                LOG.debug("createReport() started");
068                this.document = new Document();
069    
070                String destinationDirectory = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.REPORTS_DIRECTORY_KEY);
071    
072                SimpleDateFormat sdf = new SimpleDateFormat(CamsConstants.DateFormats.YEAR_MONTH_DAY_NO_DELIMITER + "_" + CamsConstants.DateFormats.MILITARY_TIME_NO_DELIMITER);
073    
074                String filename = destinationDirectory + File.separator + "cam" + File.separator + CamsConstants.Report.FILE_PREFIX + "_" + CamsConstants.Depreciation.REPORT_FILE_NAME + "_" + sdf.format(dateTimeService.getCurrentDate()) + "." + CamsConstants.Report.REPORT_EXTENSION;
075    
076                Font headerFont = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL);
077    
078                PageHelper helper = new PageHelper();
079                helper.runDate = dateTimeService.getCurrentDate();
080                helper.headerFont = headerFont;
081                helper.title = CamsConstants.Depreciation.DEPRECIATION_REPORT_TITLE;
082    
083                writer = PdfWriter.getInstance(this.document, new FileOutputStream(filename));
084                writer.setPageEvent(helper);
085    
086                this.document.open();
087    
088                // Generate body of document.
089                this.generateReportLogBody(reportLog);
090                this.generateReportErrorLog(errorMsg);
091    
092            }
093            catch (Exception e) {
094                throw new RuntimeException("DepreciationReport.generateReport(List<String[]> reportLog, List<String> errorLog) - Error on report generation: " + e.getMessage());
095            }
096            finally {
097                if ((this.document != null) && this.document.isOpen()) {
098                    this.document.close();
099                }
100            }
101        }
102    
103        /**
104         * This method adds the log lines into the report
105         * 
106         * @param reportLog
107         */
108        private void generateReportLogBody(List<String[]> reportLog) {
109            try {
110                Font font = FontFactory.getFont(FontFactory.HELVETICA, 9, Font.NORMAL);
111                int columnwidths[];
112                columnwidths = new int[] { 40, 15 };
113    
114                Table aTable = new Table(2, linesPerPage);
115                int rowsWritten = 0;
116                for (String[] columns : reportLog) {
117                    if (pageNumber == 0 || line >= linesPerPage) {
118                        if (pageNumber > 0) {
119                            this.document.add(aTable);
120                        }
121                        int elementsLeft = reportLog.size() - rowsWritten;
122                        int rowsNeeded = (elementsLeft >= linesPerPage ? linesPerPage : elementsLeft);
123                        this.document.newPage();
124    
125                        this.generateColumnHeaders();
126    
127                        aTable = new Table(2, rowsNeeded); // 12 columns, 11 rows.
128    
129                        aTable.setAutoFillEmptyCells(true);
130                        aTable.setPadding(3);
131                        aTable.setWidths(columnwidths);
132                        aTable.setWidth(100);
133                        aTable.setBorder(Rectangle.NO_BORDER);
134    
135                        line = 0;
136                        pageNumber++;
137                    }
138                    rowsWritten++;
139    
140                    Cell cell;
141                    cell = new Cell(new Phrase(columns[0], font));
142                    cell.setHorizontalAlignment(Element.ALIGN_LEFT);
143                    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
144                    aTable.addCell(cell);
145    
146                    cell = new Cell(new Phrase(columns[1], font));
147                    cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
148                    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
149                    aTable.addCell(cell);
150                    line++;
151                }
152                this.document.add(aTable);
153            }
154            catch (DocumentException de) {
155                throw new RuntimeException("DepreciationReport.generateReportLogBody(List<String[]> reportLog) - error: " + de.getMessage());
156            }
157        }
158    
159        /**
160         * This method adds any error to the report
161         * 
162         * @param errorMsg
163         */
164        private void generateReportErrorLog(String errorMsg) {
165            try {
166                Font font = FontFactory.getFont(FontFactory.HELVETICA, 9, Font.NORMAL);
167                Paragraph p1 = new Paragraph();
168    
169                int rowsWritten = 0;
170                if (!errorMsg.equals("")) {
171                    this.generateErrorColumnHeaders();
172    
173                    p1 = new Paragraph(new Chunk(errorMsg, font));
174                    this.document.add(p1);
175                    line++;
176                }
177            }
178            catch (Exception de) {
179                throw new RuntimeException("DepreciationReport.generateReportErrorLog(List<String> reportLog) - Report Generation Failed: " + de.getMessage());
180            }
181        }
182    
183        /**
184         * This method creates a report group for the error message on the report
185         * 
186         * @throws DocumentException
187         */
188        private void generateErrorColumnHeaders() throws DocumentException {
189            try {
190                int headerwidths[] = { 60 };
191    
192                Table aTable = new Table(1, 1); // 2 columns, 1 rows.
193    
194                aTable.setAutoFillEmptyCells(true);
195                aTable.setPadding(3);
196                aTable.setWidths(headerwidths);
197                aTable.setWidth(100);
198    
199                Cell cell;
200    
201                Font font = FontFactory.getFont(FontFactory.HELVETICA, 9, Font.NORMAL);
202    
203                cell = new Cell(new Phrase("Error(s)", font));
204                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
205                cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
206                cell.setGrayFill(0.9f);
207                aTable.addCell(cell);
208    
209                this.document.add(aTable);
210    
211            }
212            catch (Exception e) {
213                throw new RuntimeException("DepreciationReport.generateErrorColumnHeaders() - Error: " + e.getMessage());
214            }
215        }
216    
217        /**
218         * This method inserts the depreciation date on the report
219         * 
220         * @param sDepreciationDate private void generateDepreciationDateLabel(String sDepreciationDate) { try { int headerwidths[] = {
221         *        100 }; Table aTable = new Table(1, 1); // 1 columns, 1 rows. aTable.setAutoFillEmptyCells(true); aTable.setPadding(3);
222         *        aTable.setWidths(headerwidths); aTable.setWidth(100); aTable.setBorder(0); Cell cell; Font font =
223         *        FontFactory.getFont(FontFactory.HELVETICA, 11, Font.NORMAL); cell = new Cell(new Phrase("Depreciation Date:
224         *        "+sDepreciationDate, font)); cell.setHorizontalAlignment(Element.ALIGN_CENTER);
225         *        cell.setVerticalAlignment(Element.ALIGN_CENTER); cell.setBorder(0); aTable.addCell(cell); this.document.add(aTable); }
226         *        catch (Exception e) { throw new RuntimeException("DepreciationReport.generateDepreciationDateLabel() - Error: " +
227         *        e.getMessage()); } }
228         */
229    
230        /**
231         * This method creates the headers for the report statistics
232         */
233        private void generateColumnHeaders() {
234            try {
235                int headerwidths[] = { 40, 15 };
236    
237                Table aTable = new Table(2, 1); // 2 columns, 1 rows.
238    
239                aTable.setAutoFillEmptyCells(true);
240                aTable.setPadding(3);
241                aTable.setWidths(headerwidths);
242                aTable.setWidth(100);
243    
244                Cell cell;
245    
246                Font font = FontFactory.getFont(FontFactory.HELVETICA, 9, Font.NORMAL);
247    
248                cell = new Cell(new Phrase(SpringContext.getBean(KualiConfigurationService.class).getPropertyString(CamsKeyConstants.Depreciation.MSG_REPORT_DEPRECIATION_HEADING1), font));
249                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
250                cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
251                cell.setGrayFill(0.9f);
252                aTable.addCell(cell);
253    
254                cell = new Cell(new Phrase(SpringContext.getBean(KualiConfigurationService.class).getPropertyString(CamsKeyConstants.Depreciation.MSG_REPORT_DEPRECIATION_HEADING2), font));
255                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
256                cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
257                cell.setGrayFill(0.9f);
258                aTable.addCell(cell);
259                this.document.add(aTable);
260    
261            }
262            catch (Exception e) {
263                throw new RuntimeException("DepreciationReport.generateColumnHeaders() - Error: " + e.getMessage());
264            }
265        }
266    
267    
268        /**
269         * An inner class to help set up the PDF that is written
270         */
271        class PageHelper extends PdfPageEventHelper {
272            public Date runDate;
273            public Font headerFont;
274            public String title;
275    
276            /**
277             * Writes the footer on the last page
278             * 
279             * @see com.lowagie.text.pdf.PdfPageEventHelper#onEndPage(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document)
280             */
281            public void onEndPage(PdfWriter writer, Document document) {
282                try {
283                    Font titleFont = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL);
284                    Font font = FontFactory.getFont(FontFactory.HELVETICA, 8, Font.NORMAL);
285    
286                    Rectangle page = document.getPageSize();
287                    PdfPTable head = new PdfPTable(3);
288    
289                    int[] widths = { 15, 70, 15 };
290                    head.setWidths(widths);
291    
292                    SimpleDateFormat sdf = new SimpleDateFormat(CamsConstants.DateFormats.MONTH_DAY_YEAR + " " + CamsConstants.DateFormats.MILITARY_TIME);
293    
294                    PdfPCell cell = new PdfPCell(new Phrase(sdf.format(runDate), font));
295                    cell.setBorder(Rectangle.NO_BORDER);
296                    head.addCell(cell);
297    
298                    cell = new PdfPCell(new Phrase(title, titleFont));
299                    cell.setBorder(Rectangle.NO_BORDER);
300                    cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
301                    head.addCell(cell);
302    
303                    cell = new PdfPCell(new Phrase("Page: " + new Integer(writer.getPageNumber()), font));
304                    cell.setBorder(Rectangle.NO_BORDER);
305                    cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
306                    head.addCell(cell);
307    
308                    head.setTotalWidth(page.width() - document.leftMargin() - document.rightMargin());
309                    head.writeSelectedRows(0, -1, document.leftMargin(), page.height() - document.topMargin() + head.getTotalHeight(), writer.getDirectContent());
310                }
311                catch (Exception e) {
312                    throw new ExceptionConverter(e);
313                }
314            }
315        }
316    }