Tools.PostProcessing.java Source code

Java tutorial

Introduction

Here is the source code for Tools.PostProcessing.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Tools;

import Files.XLSX2BatchHandler;
import PDF.PDFNumbering;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.util.PDFTextStripper;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import Utilities.GlobalVar;
import Utilities.MyDate;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.apache.pdfbox.cos.COSName.T;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.util.PDFMergerUtility;
import static org.icepdf.ri.common.FileExtensionUtils.pdf;

/**
 *  This class take audited PDF and color leave log, and change the color of deleted leave form on the log.
 * @author SPC Cui
 */
class PostProcessing {
    private final boolean VERIFY_WITH_LISTING = false; //verify the sequence number with the number on 80/80 listing
    private final Map<String, Map<String, String>> LEGIT_LV_MAP_FOR_COLOR_LV_LOG; // key = ssn, a list of map which is {key = ctrlNum, value = seq};
    // private final Map<String, Map<String, String>> LEGIT_LV_MAP_FOR_CEDMS_FILE;  // key = ssn, a list of map which is {key = ctrlNum, value = seq};
    private String PRE_PROC_PDF_FILE_NAME = null;
    private String DTL_PDF_FILE_NAME = null;
    private String LISTING_PDF_FILE_NAME = null;
    private String COLORED_LV_LOG_FILE_NAME = null;
    private Map<String, Integer> PROC_STATUS_MAP; // process status by colors, key = ssn + ctrlNum, value = errCode
    private String CYCLE = null;
    private final int FID_LINE_LENGTH = 21;
    private String ADSN;

    // pre: the pdf file is the 
    public PostProcessing(String dtlFileName, String listingFileName, String preprocessedFileName,
            String coloredLeaveLogFileName, String adsn) throws IOException {
        DTL_PDF_FILE_NAME = dtlFileName;
        LISTING_PDF_FILE_NAME = listingFileName;
        PRE_PROC_PDF_FILE_NAME = preprocessedFileName;
        COLORED_LV_LOG_FILE_NAME = coloredLeaveLogFileName;
        ADSN = adsn;

        Pattern pattern1 = Pattern.compile("[0][A-Z]{2}[0][1-6] [0-9]{9} [A-Z ]{5}"); //0SB03 624238103 OH CH
        Pattern pattern2 = Pattern.compile("[0][A-Z]{2}[0][1-6] [0-9]{9} [A-Z]{4}"); //0SB03 624238103 CARL
        boolean SB03only = true; // 80/80 listing contains SB03 only.
        PDDocument listingPdf = PDDocument.load(listingFileName);
        LEGIT_LV_MAP_FOR_COLOR_LV_LOG = new TreeMap<>();
        //  LEGIT_LV_MAP_FOR_CEDMS_FILE = new TreeMap<>(); 
        PROC_STATUS_MAP = new TreeMap<>();
        PDFTextStripper pdfStripper = new PDFTextStripper();
        String res = pdfStripper.getText(listingPdf);
        // System.out.println(res);
        String[] data = res.split("\n");
        int whichLine = 999;
        List<String> tempStore = new ArrayList<>(); //temp stores a list of{"ssn first5", "seqNum1", "ssn first5", "seqNum1", ....};
        for (String text : data) {
            if (text.contains("CYCLE NUM: ")) {
                String[] info = text.split("CYCLE NUM: ");
                if (info.length == 2) {
                    CYCLE = info[1].trim();
                }
            }
            //            String truncatedText = null;
            //            if(text.length() == FID_LINE_LENGTH){
            //                truncatedText = text.substring(0, FID_LINE_LENGTH);
            //            } else if (text.length() == FID_LINE_LENGTH - 1){
            //                truncatedText = text + " ";
            //            } else {
            //                truncatedText = "bad";  // will fail the match test. 
            //            }
            Matcher m1 = pattern1.matcher(text.trim()); //last name contains less or more than four chars
            // Matcher m2 = pattern1.matcher(text.trim());  // last name contains only four chars
            if (m1.matches() || pattern2.matcher(text.trim()).matches()) {
                if (text.contains("0SB03")) {
                    whichLine = 0;
                    String key = text.replaceAll("0SB03", "").trim();
                    //  System.out.println(key);
                    String ssn = key.substring(0, 9);
                    tempStore.add(ssn);
                } else {
                    SB03only = false;
                }
            }
            if (whichLine == 1) {
                String dataCard = text.replaceAll(" ", ""); //151207151218A0122MA16030000
                String ctrlNum = dataCard.substring(17, 24);
                //System.out.println(ctrlNum);
                tempStore.add(ctrlNum);
            }
            if (whichLine == 2) { // two lines after SB03
                String[] tokens = text.split(" ");
                String seqNumber = tokens[1];
                // System.out.println(seqNumber);
                tempStore.add(seqNumber);
            }
            whichLine++;
        }
        //System.out.println(tempStore);
        Iterator<String> it = tempStore.iterator();

        while (it.hasNext()) {
            String ssn = it.next();
            String ctrlNum = it.next();
            String seqNumString = it.next();
            if (!LEGIT_LV_MAP_FOR_COLOR_LV_LOG.containsKey(ssn)) {
                Map<String, String> map = new TreeMap<>();
                map.put(ctrlNum, seqNumString);
                LEGIT_LV_MAP_FOR_COLOR_LV_LOG.put(ssn, map);
            } else {
                Map<String, String> map = LEGIT_LV_MAP_FOR_COLOR_LV_LOG.get(ssn);
                map.put(ctrlNum, seqNumString);
                LEGIT_LV_MAP_FOR_COLOR_LV_LOG.put(ssn, map);
            }
        }
        listingPdf.close();
        if (SB03only) {
            PROC_STATUS_MAP = generateXLSXforS1(COLORED_LV_LOG_FILE_NAME);
            // JOptionPane.showMessageDialog(null, " *_forS1.xlsx is created.  Post-processing is complete! \n");
        } else {
            JOptionPane.showMessageDialog(null,
                    "[Warning] 80/80 Listing contains some transactions other than SB03!");
        }
    }

    // generate a colored leave log including auditor deleted transactions, return the xlsx name for the colored leave log with 
    // deleted transaction info;  return a map that contains key = ssn+ctrlNum, value = statusCode
    private Map<String, Integer> generateXLSXforS1(String XLSXfileName) throws FileNotFoundException, IOException {
        Map<String, Integer> statusMap = null;
        File myFile = new File(XLSXfileName);

        FileInputStream fis = new FileInputStream(myFile);
        XSSFWorkbook myWorkBook = new XSSFWorkbook(fis);

        //Return first sheet from the XLSX workbook
        XSSFSheet mySheet = myWorkBook.getSheetAt(0);
        List<String> errorList = new ArrayList<>();
        Map<String, Map<String, List<String>>> leaves = new HashMap<String, Map<String, List<String>>>();
        //Get iterator to all the rows in current sheet
        Iterator<Row> rowIterator = mySheet.iterator();
        int lineCount = 1;
        // Traversing over each row of XLSX file
        if (rowIterator.hasNext()) {

            Row headerRow = rowIterator.next(); //skip the header row
            Iterator<Cell> it = headerRow.cellIterator();
            int numCell = 0;
            List<String> keyList = new ArrayList<String>(); //keep track info of each column

            while (it.hasNext()) {
                keyList.add(it.next().getStringCellValue()); // add the title in xlsx to keyList                  
                numCell++;
            }
            if (numCell == GlobalVar.LEAVE_TITLES_V2.length) {
                // System.out.println("XLSX2BatchHandler.java: V2, UCFR is not loaded.");
                //                int globalCount = 1;
                DataFormatter df = new DataFormatter();
                statusMap = new TreeMap<>();
                while (rowIterator.hasNext()) {
                    lineCount++;
                    Row row = rowIterator.next();
                    Cell ctrlNumCell = row.getCell(GlobalVar.CTRL_NUM_CELL_INDEX_V2);
                    Cell ssnCell = row.getCell(GlobalVar.FULL_SSN_CELL_INDEX_V2);
                    String fullSSN = GlobalVar.fullSSNgenerator(df.formatCellValue(ssnCell));
                    colorDeletedLeaves(fullSSN, ctrlNumCell, myWorkBook, statusMap);
                }
                // output to a new xlsx file
                fis.close();
                FileOutputStream output;
                String targetFile = null;
                if (XLSXfileName.contains(".xlsx")) {
                    targetFile = XLSXfileName.replace(".xlsx", "_forS1.xlsx");
                } else {
                    targetFile = XLSXfileName + "_forS1.xlsx";
                }
                output = new FileOutputStream(targetFile);
                myWorkBook.write(output);
                output.close();

            } else {
                JOptionPane.showMessageDialog(null, "XLSX file format is incorrect! Must be full SSN format");
            }
        }
        return statusMap;
    }

    //color the ctrlNum cell if the leave forms are delteed by the auditors, generate PROC_STATUS_MAP
    private void colorDeletedLeaves(String ssn, Cell ctrlNumCell, XSSFWorkbook myWorkBook,
            Map<String, Integer> statusMap) {
        String ctrlNumString = null;
        if (ctrlNumCell != null && ctrlNumCell.getStringCellValue() != null) {
            ctrlNumString = ctrlNumCell.getStringCellValue().trim();
            // color valid leaves
            CellStyle style = ctrlNumCell.getCellStyle();
            String key = ssn + ctrlNumString;
            if (style.getFillForegroundColor() == IndexedColors.GREEN.getIndex()) {
                statusMap.put(key, GlobalVar.NO_ERR);
                if (!LEGIT_LV_MAP_FOR_COLOR_LV_LOG.containsKey(ssn)) { // Map< SSN, Map<ctrlNum, signOutdate>>
                    style.setFillForegroundColor(GlobalVar.AUDITOR_DELETED_COLOR);
                    style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                    ctrlNumCell.setCellStyle(style);
                    statusMap.put(key, GlobalVar.AUDIT_DELETE_ERR);
                } else { // contains SSN
                    Map<String, String> list = LEGIT_LV_MAP_FOR_COLOR_LV_LOG.get(ssn);
                    if (!list.keySet().contains(ctrlNumString)) {
                        style.setFillForegroundColor(GlobalVar.AUDITOR_DELETED_COLOR);
                        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
                        ctrlNumCell.setCellStyle(style);
                        statusMap.put(key, GlobalVar.AUDIT_DELETE_ERR);
                    }
                }
            } else if (style.getFillForegroundColor() == GlobalVar.BAD_STATUS_COLOR) {
                statusMap.put(key, GlobalVar.BAD_STATUS_ERR);
            } else if (style.getFillForegroundColor() == GlobalVar.ETS_STATUS_COLOR) {
                statusMap.put(key, GlobalVar.ETS_ERR);
            } else if (style.getFillForegroundColor() == GlobalVar.DUPLICATE_LV_COLOR) {
                statusMap.put(key, GlobalVar.DUPLICATE_LV_ERR);
            } else if (style.getFillForegroundColor() == GlobalVar.DUPLICATE_CTRL_NUM_COLOR) {
                statusMap.put(key, GlobalVar.DUPLICATE_CTRL_NUM_ERR);
            } else if (style.getFillForegroundColor() == GlobalVar.AFTER_PCS_COLOR) {
                statusMap.put(key, GlobalVar.AFTER_PCS_ERR);
            } else if (style.getFillForegroundColor() == GlobalVar.INPROCESSING_COLOR) {
                statusMap.put(key, GlobalVar.INPROCESSING_ERR);
            } else if (style.getFillForegroundColor() == GlobalVar.WRONG_SSN_COLOR) {
                statusMap.put(key, GlobalVar.WRONG_SSN_ERR);
            } else if (style.getFillForegroundColor() == GlobalVar.OVERLAP_LV_COLOR) {
                statusMap.put(key, GlobalVar.OVERLAP_LV_ERR);
            } else if (style.getFillForegroundColor() == GlobalVar.AUDITOR_DELETED_COLOR) {
                statusMap.put(key, GlobalVar.AUDIT_DELETE_ERR);
            } else {
                statusMap.put(key, GlobalVar.IN_CYCLE_DUPLICATION_INVALID_FIRST_FIVE_ERR);
            }
        }
    }

    ////////////////////////////////////// end of the constructor ///////////////////    
    //    // pre: must be V2 (full ssn type xlsx)
    //    // use the title as a key for the values store in the same column
    //    private void rowContainerBuilder(Map<String, String> rowContainer,List<String> keyList,Iterator<Cell> cellIterator) {
    //        int keys = 0;
    //        while (cellIterator.hasNext()) {
    //            Cell cell = cellIterator.next();                              
    //            if (keys == GlobalVar.CTRL_NUM_CELL_INDEX_V2 ) {
    //                String value = cell.getStringCellValue();
    //                rowContainer.put(keyList.get(keys), value);                                
    //            } else if (keys == GlobalVar.FULL_SSN_CELL_INDEX_V2) {
    //                int type = cell.getCellType();
    //                String fullSSN = null;
    //                if (type == HSSFCell.CELL_TYPE_STRING) {
    //                    fullSSN = cell.getStringCellValue(); //string type ssn
    //                    fullSSN = fullSSN.replaceAll("-","");
    //                } else {
    //                    DataFormatter df = new DataFormatter();
    //                    //SimpleDateFormat fmt = new SimpleDateFormat("yyMMdd");   
    //                    fullSSN = df.formatCellValue(cell); //return ***-**-****
    //                }
    //                fullSSN = GlobalVar.fullSSNgenerator(fullSSN);
    //                rowContainer.put(keyList.get(keys), fullSSN); 
    //            } else if (keys == GlobalVar.SIGN_OUT_DATE_CELL_INDEX_V2 || keys == GlobalVar.SIGN_IN_DATE_CELL_INDEX_V2) {
    //                DataFormatter df = new DataFormatter();
    //                String dateString = df.formatCellValue(cell);
    //                rowContainer.put(keyList.get(keys), dateString); 
    //            } else if (keys == GlobalVar.LEAVE_AREA_CELL_INDEX_V2) {
    //                int type = cell.getCellType();
    //                String value = null;
    //                if (type == HSSFCell.CELL_TYPE_STRING){
    //                    value = GlobalVar.getDMOLeaveArea(cell.getStringCellValue());
    //                } else if(type == HSSFCell.CELL_TYPE_NUMERIC) {
    //                    value = GlobalVar.getDMOLeaveArea(cell.getNumericCellValue()); //read a double and return string
    //                } 
    //                rowContainer.put(keyList.get(keys), value); 
    //            } else if (keys == GlobalVar.LEAVE_TYPE_CELL_INDEX_V2) {                                
    //                String value = GlobalVar.getDMOLeaveType(cell.getStringCellValue());                                
    //                rowContainer.put(keyList.get(keys), value); 
    //            }                         
    //            keys ++;    
    //        }
    //    }

    ////////////////////////////////////// Start of rejected pdf file and processed pdf file ///////////////////
    // given the pre-processed file name
    // generate a pdf of all the rejects and a pdf of all the legit leave forms
    // return the file name of the pdf of all the legit leave forms.
    private String generateProcessedAndRejectPDFs(String preProcPdfFileName)
            throws IOException, COSVisitorException {
        PDDocument pdf = PDDocument.load(preProcPdfFileName);
        PDDocument rejectPdf = new PDDocument();
        PDDocument cedmsPdf = new PDDocument();
        //String rejectPdfFileName = preProcPdfFileName.replace(".pdf", "_forReject.pdf");  
        //String cedmsPdfFileName = preProcPdfFileName.replace(".pdf", "_forCEDMS.pdf");  
        int pageNum = pdf.getNumberOfPages(); //total number of pages in the pdf file
        // add reject page into rejectPdf
        PDFTextStripper pdfStripper = new PDFTextStripper();
        int seqNumber = 1;
        boolean isLastReject = true; // last page status  
        for (int i = 0; i < pageNum; i++) {
            PDPage page = (PDPage) pdf.getDocumentCatalog().getAllPages().get(i);
            int pageIndex = i + 1;
            pdfStripper.setStartPage(pageIndex);
            pdfStripper.setEndPage(pageIndex);
            String res = pdfStripper.getText(pdf);
            // System.out.println(res);

            if (res.contains(GlobalVar.PRE_PROC_KEY_SYMBOL)) {
                String[] data = GlobalVar.getCtrlNumAndfullSSN(res);
                String ctrlNum = data[0];
                String fullSSN = data[1];
                // System.out.println("full ssn:" + fullSSN + ". ctrl num:" + ctrlNum);
                //                if(LEGIT_LV_MAP_FOR_COLOR_LV_LOG.containsKey(fullSSN)){
                //                   // System.out.println("ctrl num: " + LEGIT_LV_MAP.get(fullSSN));
                //                }
                if (LEGIT_LV_MAP_FOR_COLOR_LV_LOG.containsKey(fullSSN)
                        && LEGIT_LV_MAP_FOR_COLOR_LV_LOG.get(fullSSN).containsKey(ctrlNum)) {
                    // System.out.println("Good leave");
                    int thisSeqNumber = Integer.parseInt(LEGIT_LV_MAP_FOR_COLOR_LV_LOG.get(fullSSN).get(ctrlNum));
                    if (thisSeqNumber == seqNumber) {
                        cedmsPdf.addPage(page);
                        //LEGIT_LV_MAP_FOR_COLOR_LV_LOG.get(fullSSN).remove(ctrlNum);  // remove 
                        isLastReject = false;
                        seqNumber++;
                    } else {
                        String msg = "Order might be incorrect or there is a duplicate! ssn: " + fullSSN
                                + " ctrl num: " + ctrlNum + ". Seq number is: " + seqNumber;
                        //JOptionPane.showMessageDialog(null, msg);
                        System.out.println(msg);
                    }
                } else {
                    rejectPdf.addPage(page);
                    drawComments(rejectPdf, page, fullSSN, ctrlNum);
                    isLastReject = true;
                }
            } else { // add the supporting documents to the last pdf file
                if (isLastReject) {
                    rejectPdf.addPage(page);
                } else {
                    cedmsPdf.addPage(page);
                }
            }
        }

        String cedmsPdfFileName = null;
        String rejectPdfFileName = null;
        if (preProcPdfFileName.contains(".pdf")) {
            cedmsPdfFileName = preProcPdfFileName.replace(".pdf", GlobalVar.PRE_CEDMS_PDF);
            rejectPdfFileName = preProcPdfFileName.replace(".pdf", "_forReject.pdf");
        } else if (preProcPdfFileName.contains(".PDF")) {
            cedmsPdfFileName = preProcPdfFileName.replace(".PDF", GlobalVar.PRE_CEDMS_PDF);
            rejectPdfFileName = preProcPdfFileName.replace(".PDF", "_forReject.pdf");
        } else {
            JOptionPane.showMessageDialog(null, "Invalid pre-processing file.");
        }

        //        preProcPdfFileName.replace(".pdf", "_forReject.pdf"); 
        //        if (preProcPdfFileName.contains(".pdf")){
        //           cedmsPdfFileName = preProcPdfFileName.replace(".pdf", GlobalVar.PRE_CEDMS_PDF); 
        //        } else if (preProcPdfFileName.contains(".PDF")) {
        //           cedmsPdfFileName = preProcPdfFileName.replace(".PDF", GlobalVar.PRE_CEDMS_PDF);
        //        } else {
        //           JOptionPane.showMessageDialog(null, "Invalid pre-processing file."); 
        //        }
        //        
        if (rejectPdf.getNumberOfPages() > 0 && cedmsPdf.getNumberOfPages() > 0) {
            cedmsPdf.save(cedmsPdfFileName);
            rejectPdf.save(rejectPdfFileName);
            //            JOptionPane.showMessageDialog(null, "The ready-for-upload and the rejected "
            //                    + "leave forms are saved in *_forCEDMS.pdf and *_forReject.pdf, respectively.");
        } else if (rejectPdf.getNumberOfPages() > 0) {
            rejectPdf.save(rejectPdfFileName);
            cedmsPdfFileName = null; // no cedms file is generated.
            //            JOptionPane.showMessageDialog(null, "The rejected leave forms are saved in *_forReject.pdf.");
        } else if (cedmsPdf.getNumberOfPages() > 0) {
            cedmsPdf.save(cedmsPdfFileName);
            //            JOptionPane.showMessageDialog(null, "The ready-for-upload leave forms are saved in *_forCEDMS.pdf."); 
        }
        rejectPdf.close();
        cedmsPdf.close();
        pdf.close();
        return cedmsPdfFileName;
    }

    // given the ssn, ctrl num, processStatus map, add the comment on the rejected page
    private void drawComments(PDDocument pdf, PDPage page, String ssn, String ctrlNum) throws IOException {
        int errCode = GlobalVar.NO_ERR;
        String key = ssn + ctrlNum;
        if (PROC_STATUS_MAP.containsKey(key)) {
            errCode = PROC_STATUS_MAP.get(key);
        }

        PDPageContentStream stream = new PDPageContentStream(pdf, page, true, false);
        stream.beginText();
        stream.setFont(PDType1Font.HELVETICA, GlobalVar.COMMENT_FONT_SIZE);
        stream.moveTextPositionByAmount(GlobalVar.COMMENT_TEXT_X_POSITION, GlobalVar.COMMENT_TEXT_Y_POSITION);
        stream.drawString(GlobalVar.commentMap(errCode, ADSN));
        stream.endText();
        stream.close();
    }

    ////////////////////////////////////// end of rejected pdf file and CEDMS pdf file ///////////////////

    // given the pre-processed pdf and processed file (with leave)
    // number all cedms pdf and return the resulting file name
    private String pdfNumbering(String processedPdfFileName) throws IOException, COSVisitorException {
        PDDocument cedmsPdf = PDDocument.load(processedPdfFileName);
        List pages = cedmsPdf.getDocumentCatalog().getAllPages();
        PDFTextStripper pdfStripper = new PDFTextStripper();
        String res = pdfStripper.getText(cedmsPdf);
        //System.out.println(res);
        Boolean isPreProcessed = res.contains(GlobalVar.PRE_PROC_KEY_SYMBOL); // check if the file is pre-processed.
        Boolean isNumbered = res.contains("/0");
        Iterator<PDPage> iter = pages.iterator();
        int sequenceNum = 1; // start from 0001
        if (isPreProcessed && isNumbered) {
            GlobalVar.updateSeqNum(cedmsPdf, CYCLE); // update the sequence number
        } else if (isPreProcessed) { // first time
            int pageNumber = 1;

            while (iter.hasNext()) {
                PDPage page = iter.next();

                pdfStripper.setStartPage(pageNumber);
                pdfStripper.setEndPage(pageNumber);
                res = pdfStripper.getText(cedmsPdf);
                // == numbering
                if (res.contains(GlobalVar.PRE_PROC_KEY_SYMBOL)) {
                    String[] data = res.split(GlobalVar.PRE_PROC_KEY_SYMBOL);

                    if (VERIFY_WITH_LISTING) { //verify the sequence number with the number on 80/80 listing
                        String ssn = data[0].substring(data[0].length() - GlobalVar.SSN_LEN, data[0].length());
                        String ctrlNum = data[1].substring(0, -GlobalVar.MAX_CTRL_NUM_LEN);
                        String seqNum = LEGIT_LV_MAP_FOR_COLOR_LV_LOG.get(ssn).get(ctrlNum);
                        int seqNumberFrom8080Listing = Integer.parseInt(seqNum);
                        if (seqNumberFrom8080Listing != sequenceNum) {
                            JOptionPane.showMessageDialog(null,
                                    ssn + " " + ctrlNum + " seq num: " + seqNum + " do not match 80/80 listing");
                        }
                    }

                    PDPageContentStream stream = new PDPageContentStream(cedmsPdf, page, true, false);
                    stream.beginText();
                    stream.setFont(PDType1Font.HELVETICA, GlobalVar.SEQ_NUM_FONT_SIZE);
                    stream.moveTextPositionByAmount(GlobalVar.SEQ_NUM_TEXT_X_POSITION,
                            GlobalVar.SEQ_NUM_TEXT_Y_POSITION);
                    stream.setTextRotation(3.14 / 2, GlobalVar.SEQ_NUM_TEXT_X_POSITION,
                            GlobalVar.SEQ_NUM_TEXT_Y_POSITION); // rotate text 90 degree at x = 600, y = 400
                    //stream.drawString(CYCLE + "/" + seqNum);
                    stream.drawString(CYCLE + "/" + GlobalVar.globalCountGenerator5Digit(sequenceNum));
                    sequenceNum++;
                    stream.endText();
                    stream.close();
                }
                pageNumber++;
                // end of numbering
            }
        }
        //        String suffix = "_" + CYCLE +" Numbered.pdf";
        //        String fileName = DTL_PDF_FILE_NAME.replace(".pdf", suffix);
        String fileName = processedPdfFileName.replaceAll(".pdf", GlobalVar.NUMBERED_PDF);
        cedmsPdf.save(fileName);
        cedmsPdf.close();
        return fileName;
    }

    // given the numbered and processed leave forms (with rejects removed)
    // generate ready-for-CEDMS upload pdf file
    private void mergeDTLListingAndCEDMS(String numberedLeaveForms) throws IOException, COSVisitorException {
        PDFMergerUtility ut = new PDFMergerUtility();
        ut.addSource(DTL_PDF_FILE_NAME);
        ut.addSource(LISTING_PDF_FILE_NAME);
        ut.addSource(numberedLeaveForms);
        String cedmsPdfFileName = DTL_PDF_FILE_NAME.replace(".pdf", "_forCEDMS.pdf");
        cedmsPdfFileName = cedmsPdfFileName.replace("DTL ", "");
        ut.setDestinationFileName(cedmsPdfFileName);
        ut.mergeDocuments();

    }

    // generate one pdf file for CEDMS upload, one pdf of rejects     
    public void generateAll() throws IOException, COSVisitorException {
        //generate a temp file of processed leave forms, a temp file of rejected leave forms
        String preCEDMSFile = generateProcessedAndRejectPDFs(PRE_PROC_PDF_FILE_NAME);
        if (preCEDMSFile != null) { // a temp file of processed leave forms generated
            String numberedLeaveForms = pdfNumbering(preCEDMSFile); //number the temp file of processed leave forms
            mergeDTLListingAndCEDMS(numberedLeaveForms); // generate a pdf file of the cycle which is ready to upload on CEDMS
            // delete two temp files
            File tempfile1 = new File(numberedLeaveForms);
            tempfile1.delete();
            File tempfile2 = new File(preCEDMSFile);
            tempfile2.delete();
            System.out.println("PostProcessing.java: CEDMS file is generated.");
        } else {
            System.out.println(
                    "PostProcessing.java: None of the transactions processed. CEDMS file is not generated.");
        }
    }

}