S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

iTextでしおりをつける

結構イロイロ難しいね。
JasperReportsでPDFファイル作って、そのPDFファイルを結合してしおりをつける(PdfTest#mergePdf1)。
既にあるPDFファイルを結合してしおりをつける(PdfTest#mergePdf2)。
んでも、しおりのつき方によっては、うまくいかない。
というのも、しおりのつき方っていろいろあるっぽい。
ページの先頭とか、あるページの特定の箇所?ブロック?とか。

List bm = SimpleBookmark.getBookmark(pdfReader);

で得られるブックマークのリストの要素はHashMap。
MapのKeyで"Title","Action","Page"とあるけど、既にあるPDFファイルを読み込んでみると"Title"以外がなかったり。
PdfTest#mergePdf1で自前で作成したPDFファイルのブックマークは、Mapにちゃんと"Title","Action","Page"が入ってる。
とりあえず、1ページずつ作ってしおりを作っていけばいいので、PdfTest#mergePdf1な感じで要件は実現できそうだけど、いまいちブックマークのモデルというかが納得できんなぁ〜
んで、そのブックマークのリストを設定するのはsetOutlinesってなメソッド
しおりってブックマークなんかアウトラインなんか、それともまた別のなにかなんか???
なんとなく、HTMLのAタグとNAMEタグの関係みたいなのを予想してたんだけど…


■参考サイト
iText-ページの結合
Need help with Bookmark Children when using HashMap

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.co.msr.lib.util.MapUtil;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.export.JRPdfExporter;

import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfCopyFields;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.SimpleBookmark;

public class PdfTest extends PdfPageEventHelper {
    

    public static void main(String args[]) {
        
        try {
            
            createPdf();
            
            mergePdf1();

            mergePdf2();            

        } catch (Throwable t) {
            t.printStackTrace();
        }

    }

    
    private static void createPdf() throws Throwable {
        
       JasperReport jr = JasperCompileManager.compileReport("…/template.jrxml");

        List<JasperPrint> list = new ArrayList<JasperPrint>();
        
        for ( int i = 0 ; i < 10 ; i++ ) {
                
            JRExporter exporter = new JRPdfExporter();        
            exporter.getParameters().put(JRExporterParameter.OUTPUT_STREAM, new FileOutputStream("…/createPdf" + String.valueOf(i) + ".pdf"));
                    
            Map map = new HashMap();
            map.put("value", "Test" + i);

            JasperPrint jp = JasperFillManager.fillReport(jr, map);
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jp);
            exporter.exportReport();
            
        }
        
    }

    
    private static void mergePdf1() throws Throwable {
        
        OutputStream os = new FileOutputStream("…/mergePdf1.pdf");

        PdfCopyFields copyFields = new PdfCopyFields(os);
        List bookmark = new ArrayList();
        int pageOffset = 0;
        
        for ( int i = 0 ; i < 10 ; i++ ) {
            
            PdfReader pdfReader = new PdfReader(new FileInputStream("…/createPdf"+ String.valueOf(i) + ".pdf"));
            copyFields.addDocument(pdfReader);
            
            Map map = new HashMap();
            map.put("Title", "Title " + i);
            map.put("Action", "GoTo");
            map.put("Page", (pageOffset + 1) + " Fit");        
            bookmark.add(map);
            
            pageOffset = pageOffset + pdfReader.getNumberOfPages();
            
        }
        
        copyFields.setOutlines(bookmark);
        
        copyFields.close();
        os.close();
        
    }

    
    private static void mergePdf2() throws Throwable {
        
        OutputStream os = new FileOutputStream("…/mergePdf2.pdf");

        Document doc = null;
        PdfCopy pdf = null;
        List bookmark = new ArrayList();
        int pageOffset = 0;
        for ( int i = 0 ; i < 【mergePdf2_n.pdfまで】 ; i++ ) {
            
            PdfReader pdfReader = new PdfReader(new FileInputStream("…/mergePdf2_" + String.valueOf(i) + ".pdf"));
            int pageCnt = pdfReader.getNumberOfPages();
            if (doc == null) {
                doc = new Document(pdfReader.getPageSizeWithRotation(1));
                pdf =  new PdfCopy(doc, os);
                pdf.setPageEvent(new PdfTest());
                doc.open();
            }
            
            List bm = SimpleBookmark.getBookmark(pdfReader);
            if (bm != null) {
                shiftPageNumbers(bm, pageOffset);
                bookmark.addAll(bm);
            }
            pageOffset += pageCnt;
            
            for ( int j = 0 ; j < pageCnt ; j++ ) {
                PdfImportedPage page = pdf.getImportedPage(pdfReader, j + 1);
                pdf.addPage(page);
            }
        }

        if (bookmark.isEmpty() == false) {
            pdf.setOutlines(bookmark);
        }
        
        doc.close();
        pdf.close();
        os.close();

        
    }
    
    
    private static void shiftPageNumbers(List bookmark, int offset) {
        for ( int i = 0 ; i < bookmark.size() ; i++ ) {
            Map map = (Map) bookmark.get(i);        
            map.put("Action", "GoTo");
            String pageFit = (String) map.get("Page");
            if ((pageFit != null) && (pageFit.endsWith(" Fit") == true)) {
                int page = Integer.parseInt(pageFit.substring(0, (pageFit.length() - 4)));
                map.put("Page",  (page + offset)+ " Fit");                    
            }
        }
    }

    
}