com.viettel.util.doc.DocsUtility.java Source code

Java tutorial

Introduction

Here is the source code for com.viettel.util.doc.DocsUtility.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 com.viettel.util.doc;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Resource;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.docx4j.XmlUtils;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.io.SaveToZipFile;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.R;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Tc;
import org.docx4j.wml.Text;
import org.docx4j.wml.Tr;
import org.springframework.context.MessageSource;

/**
 *
 * @author BVN-PC
 */
@SuppressWarnings("deprecation")
public class DocsUtility {

    @Resource(name = "configSource")
    public MessageSource configSource;

    WordprocessingMLPackage wordMLPackage;
    String pathTemp;

    public DocsUtility(String file, String pathTemp) {
        try {
            this.wordMLPackage = getTemplate(file);
            this.pathTemp = pathTemp;
        } catch (Docx4JException | FileNotFoundException ex) {
            Logger.getLogger(DocsUtility.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private WordprocessingMLPackage getTemplate(String name) throws Docx4JException, FileNotFoundException {
        WordprocessingMLPackage template = WordprocessingMLPackage.load(new FileInputStream(new File(name)));
        return template;
    }

    public List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
        List<Object> result = new ArrayList<>();
        if (obj instanceof JAXBElement) {
            obj = ((JAXBElement<?>) obj).getValue();
        }

        if (obj.getClass().equals(toSearch)) {
            result.add(obj);
        } else if (obj instanceof ContentAccessor) {
            List<?> children = ((ContentAccessor) obj).getContent();
            children.forEach((child) -> {
                result.addAll(getAllElementFromObject(child, toSearch));
            });

        }
        return result;
    }

    public void replacePlaceholder(String content, String placeholder) {
        List<Object> texts = getAllElementFromObject(wordMLPackage.getMainDocumentPart(), Text.class);

        texts.stream().map((text) -> (Text) text)
                .filter((textElement) -> (textElement.getValue().equals(placeholder)))
                .forEachOrdered((textElement) -> {
                    if (placeholder.contains("AZ_I")) {
                        textElement.setValue("");
                        R parent = (R) textElement.getParent();
                        File file = new File(content);
                        try {
                            ObjectFactory factory = Context.getWmlObjectFactory();
                            org.docx4j.wml.Drawing drawing = factory.createDrawing();
                            parent.getContent().add(drawing);
                            drawing.getAnchorOrInline().add(createInlineImage(file));
                        } catch (Exception ex) {
                            Logger.getLogger(DocsUtility.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    } else {
                        textElement.setValue(content);
                    }
                });
    }

    public void replaceValues(HashMap<String, String> maps) {
        maps.forEach((t, u) -> {
            replacePlaceholder(u, t);
        });
    }

    public void replaceParagraph(String placeholder, String textToAdd) {
        // 1. get the paragraph
        List<Object> paragraphs = getAllElementFromObject(wordMLPackage.getMainDocumentPart(), P.class);

        P toReplace = null;
        for (Object p : paragraphs) {
            List<Object> texts = getAllElementFromObject(p, Text.class);
            for (Object t : texts) {
                Text content = (Text) t;
                if (content.getValue().equals(placeholder)) {
                    toReplace = (P) p;
                    break;
                }
            }
        }

        // we now have the paragraph that contains our placeholder: toReplace
        // 2. split into seperate lines
        String as[] = StringUtils.splitPreserveAllTokens(textToAdd, '\n');

        for (String ptext : as) {
            // 3. copy the found paragraph to keep styling correct
            P copy = (P) XmlUtils.deepCopy(toReplace);

            // replace the text elements from the copy
            List<?> texts = getAllElementFromObject(copy, Text.class);
            if (texts.size() > 0) {
                Text textToReplace = (Text) texts.get(0);
                textToReplace.setValue(ptext);
            }

            wordMLPackage.getMainDocumentPart().getContent().add(copy);
        }

        // 4. remove the original one
        ((ContentAccessor) toReplace.getParent()).getContent().remove(toReplace);

    }

    public void replaceTable(String[] placeholders, List<Map<String, String>> textToAdd)
            throws Docx4JException, JAXBException {
        List<Object> tables = getAllElementFromObject(wordMLPackage.getMainDocumentPart(), Tbl.class);

        // 1. find the table
        Tbl tempTable = getTemplateTable(tables, placeholders[0]);
        List<Object> rows = getAllElementFromObject(tempTable, Tr.class);

        // first row is header, second row is content
        if (rows.size() == 2) {
            // this is our template row
            Tr templateRow = (Tr) rows.get(1);

            textToAdd.forEach((replacements) -> {
                // 2 and 3 are done in this method
                addRowToTable(tempTable, templateRow, replacements);
            });

            // 4. remove the template row
            tempTable.getContent().remove(templateRow);
        }
    }

    public Tbl getTemplateTable(List<Object> tables, String templateKey) throws Docx4JException, JAXBException {
        for (Object tbl : tables) {
            List<?> textElements = getAllElementFromObject(tbl, Text.class);
            for (Object text : textElements) {
                Text textElement = (Text) text;
                if (textElement.getValue() != null && textElement.getValue().equals(templateKey)) {
                    return (Tbl) tbl;
                }
            }
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    public void addRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> replacements) {
        Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
        List<?> textElements = getAllElementFromObject(workingRow, Tc.class);
        textElements.stream().map((object) -> object).forEachOrdered((cell) -> {
            Tc tc = (Tc) cell;
            List texts = getAllElementFromObject(tc, Text.class);
            for (Object textObj : texts) {
                Text text = (Text) textObj;
                String replacementValue = (String) replacements.get(text.getValue());
                if (text.getValue().contains("AZ_I")) {
                    text.setValue("");
                    File file = new File(replacementValue);
                    P paragraphWithImage;
                    try {
                        paragraphWithImage = addInlineImageToParagraph(createInlineImage(file));
                        tc.getContent().add(paragraphWithImage);
                    } catch (Exception ex) {
                        Logger.getLogger(DocsUtility.class.getName()).log(Level.SEVERE, null, ex);
                    }
                } else {
                    text.setValue(replacementValue);
                }
            }
        });

        reviewtable.getContent().add(workingRow);
    }

    private P addInlineImageToParagraph(Inline inline) {
        // Now add the in-line image to a paragraph
        ObjectFactory factory = new ObjectFactory();
        P paragraph = factory.createP();
        R run = factory.createR();
        paragraph.getContent().add(run);
        Drawing drawing = factory.createDrawing();
        run.getContent().add(drawing);
        drawing.getAnchorOrInline().add(inline);
        return paragraph;
    }

    private Inline createInlineImage(File file) throws Exception {
        byte[] bytes = convertImageToByteArray(file);

        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);

        int docPrId = 1;
        int cNvPrId = 2;

        return imagePart.createImageInline("Filename hint", "Alternative text", docPrId, cNvPrId, false);
    }

    private byte[] convertImageToByteArray(File file) throws FileNotFoundException, IOException {
        InputStream is = new FileInputStream(file);
        long length = file.length();
        // You cannot create an array using a long, it needs to be an int.
        if (length > Integer.MAX_VALUE) {
            System.out.println("File too large!!");
        }
        byte[] bytes = new byte[(int) length];
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
            offset += numRead;
        }
        // Ensure all the bytes have been read
        if (offset < bytes.length) {
            System.out.println("Could not completely read file " + file.getName());
        }
        is.close();
        return bytes;
    }

    /**
     * Create image, without specifying width
     *
     * @param wordMLPackage
     * @param bytes
     * @param filenameHint
     * @param altText
     * @param id1
     * @param id2
     * @return
     * @throws java.lang.Exception
     */
    public org.docx4j.wml.P newImage(byte[] bytes, String filenameHint, String altText, int id1, int id2)
            throws Exception {

        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);

        Inline inline = imagePart.createImageInline(filenameHint, altText, id1, id2, false);

        // Now add the inline in w:p/w:r/w:drawing
        org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
        org.docx4j.wml.P p = factory.createP();
        org.docx4j.wml.R run = factory.createR();
        p.getContent().add(run);
        org.docx4j.wml.Drawing drawing = factory.createDrawing();
        run.getContent().add(drawing);
        drawing.getAnchorOrInline().add(inline);

        return p;

    }

    /**
     * Create image, specifying width in twips
     *
     * @param wordMLPackage
     * @param bytes
     * @param filenameHint
     * @param altText
     * @param id1
     * @param id2
     * @param cx
     * @return
     * @throws java.lang.Exception
     */
    public P newImage(byte[] bytes, String filenameHint, String altText, int id1, int id2, long cx)
            throws Exception {

        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);

        Inline inline = imagePart.createImageInline(filenameHint, altText, id1, id2, cx, false);

        // Now add the inline in w:p/w:r/w:drawing
        org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
        org.docx4j.wml.P p = factory.createP();
        org.docx4j.wml.R run = factory.createR();
        p.getContent().add(run);
        org.docx4j.wml.Drawing drawing = factory.createDrawing();
        run.getContent().add(drawing);
        drawing.getAnchorOrInline().add(inline);

        return p;

    }

    public void saveToFile(String file) {
        try {
            SaveToZipFile saver = new SaveToZipFile(wordMLPackage);
            saver.save(file);
        } catch (Docx4JException ex) {
            Logger.getLogger(DocsUtility.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String saveToWord() {

        Random rand = new Random();
        int n = rand.nextInt(1000) + 1;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
        String fileName = pathTemp + sdf.format(new Date()) + n + ".docx";
        File f = new File(fileName);
        try {
            wordMLPackage.save(f);
            return fileName;
        } catch (Docx4JException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return "";
    }

    public String getBase64Word() throws IOException {
        String pathFile = saveToWord();
        try (InputStream is = new FileInputStream(pathFile)) {
            String dataFile = Base64.getEncoder().encodeToString(IOUtils.toByteArray(is));
            new File(pathFile).delete();
            return dataFile;
        }
    }

    public String saveToPdf() throws IOException {

        //configSource.getMessage("path.tempFolder", null, null)

        String pathWord = saveToWord();
        Random rand = new Random();
        int n = rand.nextInt(1000) + 1;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
        String fileName = pathTemp + sdf.format(new Date()) + n + ".pdf";

        InputStream in = new FileInputStream(new File(pathWord));
        XWPFDocument documentPdf = new XWPFDocument(in);

        OutputStream out = new FileOutputStream(fileName);
        PdfOptions options = PdfOptions.create();
        PdfConverter.getInstance().convert(documentPdf, out, options);
        new File(pathWord).delete();
        return fileName;
    }

    public String getBase64Pdf() throws IOException {

        String pdfFile = saveToPdf();
        String base64File = "";

        try (InputStream is = new FileInputStream(pdfFile)) {
            base64File = Base64.getEncoder().encodeToString(IOUtils.toByteArray(is));
        }

        new File(pdfFile).delete();
        return base64File;
    }
}