offishell.word.WordHeleper.java Source code

Java tutorial

Introduction

Here is the source code for offishell.word.WordHeleper.java

Source

/*
 * Copyright (C) 2019 offishell Development Team
 *
 * Licensed under the MIT License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *          https://opensource.org/licenses/MIT
 */
package offishell.word;

import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.util.function.UnaryOperator;

import javax.xml.namespace.QName;

import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPicture;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTEmpty;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFldChar;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTMarkup;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPTab;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageMar;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPicture;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSym;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STPageOrientation.Enum;

import kiss.I;
import kiss.Variable;

/**
 * @version 2016/06/04 18:15:54
 */
public class WordHeleper {

    /**
     * 
     */
    private WordHeleper() {
    }

    /**
     * <p>
     * Helper method to remove all comments from the specified document.
     * </p>
     * 
     * @param document A target document.
     */
    public static void clearComment(XWPFDocument document) {
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            clearComment(paragraph);
        }

        // for table
        for (XWPFTable table : document.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph para : cell.getParagraphs()) {
                        clearComment(para);
                    }
                }
            }
        }
    }

    /**
     * <p>
     * Helper method to remove all comments from the specified paragraph.
     * </p>
     * 
     * @param paragraph A target paragraph.
     */
    public static void clearComment(XWPFParagraph paragraph) {
        if (paragraph != null) {
            CTP pContext = paragraph.getCTP();

            for (int i = pContext.sizeOfCommentRangeStartArray() - 1; 0 <= i; i--) {
                pContext.removeCommentRangeStart(i);
            }

            for (int i = pContext.sizeOfCommentRangeEndArray() - 1; 0 <= i; i--) {
                pContext.removeCommentRangeEnd(i);
            }

            for (XWPFRun run : paragraph.getRuns()) {
                CTR rContext = run.getCTR();

                for (int i = rContext.sizeOfCommentReferenceArray() - 1; 0 <= i; i--) {
                    rContext.removeCommentReference(i);
                }
            }
        }
    }

    /**
     * <p>
     * Helper method to remove all text from the specified paragraph.
     * </p>
     * 
     * @param paragraph A target paragraph.
     */
    public static void clearText(XWPFParagraph paragraph) {
        if (paragraph != null) {
            for (XWPFRun run : paragraph.getRuns()) {
                run.setText("", 0);
            }
        }
    }

    /**
     * <p>
     * Helper method to clone {@link XWPFTable}.
     * </p>
     * 
     * @param in
     * @param out
     * @param converter
     */
    public static void copy(XWPFTable in, XWPFTable out, UnaryOperator<String> converter) {
        // copy context
        CTTbl outCT = out.getCTTbl();

        CTTblPr outPR = outCT.getTblPr() != null ? outCT.getTblPr() : outCT.addNewTblPr();
        outPR.set(in.getCTTbl().getTblPr());

        // copy children
        for (XWPFTableRow inRow : in.getRows()) {
            copy(inRow, out.insertNewTableRow(out.getNumberOfRows()), converter);
        }
    }

    /**
     * <p>
     * Helper method to clone {@link XWPFTableRow}.
     * </p>
     * 
     * @param in
     * @param out
     * @param converter
     */
    public static void copy(XWPFTableRow in, XWPFTableRow out, UnaryOperator<String> converter) {
        // copy context
        CTRow outCT = out.getCtRow();
        CTTrPr outPR = outCT.isSetTrPr() ? outCT.getTrPr() : outCT.addNewTrPr();
        outPR.set(in.getCtRow().getTrPr());

        // copy children
        for (XWPFTableCell inCell : in.getTableCells()) {
            copy(inCell, out.createCell(), converter);
        }
    }

    /**
     * <p>
     * Helper method to clone {@link XWPFTableCell}.
     * </p>
     * 
     * @param in
     * @param out
     * @param converter
     */
    public static void copy(XWPFTableCell in, XWPFTableCell out, UnaryOperator<String> converter) {
        // copy context
        CTTc outCTTc = out.getCTTc();
        CTTcPr outPR = outCTTc.isSetTcPr() ? outCTTc.getTcPr() : outCTTc.addNewTcPr();
        outPR.set(in.getCTTc().getTcPr());

        // clear all elements from out cell
        for (int i = out.getParagraphs().size() - 1; 0 <= i; i--) {
            out.removeParagraph(i);
        }

        // copy children
        for (XWPFParagraph inPara : in.getParagraphs()) {
            copy(inPara, out.addParagraph(), converter);
        }
    }

    /**
     * <p>
     * Helper method to clone {@link XWPFFooter}.
     * </p>
     * 
     * @param in
     * @param out
     * @param converter
     */
    public static void copy(XWPFFooter in, XWPFFooter out, UnaryOperator<String> converter) {
        // copy context

        // copy children
        for (IBodyElement element : in.getBodyElements()) {
            if (element instanceof XWPFParagraph) {
                copy((XWPFParagraph) element, out.createParagraph(), converter);
            }
        }
    }

    /**
     * <p>
     * Helper method to clone {@link XWPFParagraph}.
     * </p>
     * 
     * @param in
     * @param out
     * @param converter
     */
    public static void copy(XWPFParagraph in, XWPFParagraph out, UnaryOperator<String> converter) {
        // copy context
        ppr(out).set(in.getCTP().getPPr());

        // copy(doc, out.getDocument(), doc.getStyles().getStyle(in.getStyleID()));

        // copy children
        for (XWPFRun inRun : in.getRuns()) {
            copy(inRun, out.createRun(), converter);
        }
    }

    /**
     * <p>
     * Helper method to clone {@link XWPFRun}.
     * </p>
     * 
     * @param in
     * @param out
     * @param model
     */
    public static void copy(XWPFRun in, XWPFRun out, UnaryOperator<String> converter) {
        // copy
        out.setBold(in.isBold());
        out.setCapitalized(in.isCapitalized());
        out.setCharacterSpacing(in.getCharacterSpacing());
        out.setColor(in.getColor());
        out.setDoubleStrikethrough(in.isDoubleStrikeThrough());
        out.setEmbossed(in.isEmbossed());
        out.setFontFamily(in.getFontFamily());
        out.setFontSize(in.getFontSize());
        out.setImprinted(in.isImprinted());
        out.setItalic(in.isItalic());
        out.setKerning(in.getKerning());
        out.setShadow(in.isShadowed());
        out.setSmallCaps(in.isSmallCaps());
        out.setStrikeThrough(in.isStrikeThrough());
        out.setVerticalAlignment(out.getVerticalAlignment().toString());
        out.setTextPosition(in.getTextPosition());
        out.setUnderline(in.getUnderline());

        // copy context
        CTR inCTR = in.getCTR();
        CTRPr inPR = inCTR.getRPr();
        CTR outCTR = out.getCTR();
        CTRPr outPR = outCTR.isSetRPr() ? outCTR.getRPr() : outCTR.addNewRPr();
        outPR.set(inCTR.getRPr());
        out.setVerticalAlignment(
                inPR == null || inPR.getVertAlign() == null ? "baseline" : inPR.getVertAlign().toString());

        // // copy tab
        // CTEmpty[] tabs = inCTR.getTabArray();
        //
        // if (tabs.length != 0) {
        // out.addTab();
        // }
        outCTR.setAnnotationRefArray(inCTR.getAnnotationRefList().toArray(CTEmpty[]::new));
        outCTR.setBrArray(inCTR.getBrList().toArray(CTBr[]::new));
        outCTR.setCommentReferenceArray(inCTR.getCommentReferenceList().toArray(CTMarkup[]::new));
        outCTR.setContinuationSeparatorArray(inCTR.getContinuationSeparatorList().toArray(CTEmpty[]::new));
        outCTR.setCrArray(inCTR.getCrList().toArray(CTEmpty[]::new));
        outCTR.setDelInstrTextArray(inCTR.getDelInstrTextList().toArray(CTText[]::new));
        outCTR.setDrawingArray(inCTR.getDrawingList().toArray(CTDrawing[]::new));
        outCTR.setEndnoteRefArray(inCTR.getEndnoteRefList().toArray(CTEmpty[]::new));
        outCTR.setFldCharArray(inCTR.getFldCharList().toArray(CTFldChar[]::new));
        outCTR.setFootnoteRefArray(inCTR.getFootnoteRefList().toArray(CTEmpty[]::new));
        outCTR.setInstrTextArray(inCTR.getInstrTextList().toArray(CTText[]::new));
        outCTR.setLastRenderedPageBreakArray(inCTR.getLastRenderedPageBreakList().toArray(CTEmpty[]::new));
        outCTR.setObjectArray(inCTR.getObjectList().toArray(CTObject[]::new));
        outCTR.setPictArray(inCTR.getPictList().toArray(CTPicture[]::new));
        outCTR.setPtabArray(inCTR.getPtabList().toArray(CTPTab[]::new));
        outCTR.setSymArray(inCTR.getSymList().toArray(CTSym[]::new));
        outCTR.setTabArray(inCTR.getTabList().toArray(CTEmpty[]::new));

        // copy image
        for (XWPFPicture inPicture : in.getEmbeddedPictures()) {
            try {
                XWPFPictureData inData = inPicture.getPictureData();
                String outId = out.getDocument().addPictureData(new ByteArrayInputStream(inData.getData()),
                        inData.getPictureType());

                select(CTBlip.class, outCTR).to(blip -> blip.setEmbed(outId));
            } catch (Exception e) {
                throw I.quiet(e);
            }
        }

        // copy text
        write(out, converter.apply(in.text()));
    }

    /**
     * <p>
     * Select node by XPath.
     * </p>
     * 
     * @param type
     * @param node
     * @return
     */
    private static <T extends XmlObject> Variable<T> select(Class<T> type, XmlObject node) {
        try {
            SchemaType schema = (SchemaType) type.getField("type").get(null);
            QName qName = schema.getName();
            String name = qName.getLocalPart().replace("CT_", "").toLowerCase();
            XmlObject[] nodes = node
                    .selectPath("declare namespace ns='" + qName.getNamespaceURI() + "' .//ns:" + name);

            if (nodes.length == 0) {
                return Variable.empty();
            } else {
                return Variable.of((T) nodes[0]);
            }
        } catch (Exception e) {
            throw I.quiet(e);
        }
    }

    /**
     * <p>
     * Write the text.
     * </p>
     * 
     * @param run
     * @param text
     */
    public static void write(XWPFRun run, String text) {
        String[] lines = text.split("\n");

        if (lines.length != 0) {
            run.setText(lines[0], 0); // set first line into XWPFRun

            for (int i = 1; i < lines.length; i++) {
                run.addBreak();
                run.setText(lines[i]);
            }
        }
    }

    /**
     * <p>
     * Helper method to retrieve {@link CTPPr}.
     * </p>
     * 
     * @param paragraph
     */
    public static CTPPr ppr(XWPFParagraph paragraph) {
        CTP paraContext = paragraph.getCTP();

        return paraContext.isSetPPr() ? paraContext.getPPr() : paraContext.addNewPPr();
    }

    /**
     * <p>
     * Helper method to retrieve {@link CTSectPr}.
     * </p>
     * 
     * @param document
     */
    public static CTSectPr section(XWPFDocument document) {
        CTBody body = document.getDocument().getBody();

        return body.isSetSectPr() ? body.getSectPr() : body.addNewSectPr();
    }

    public static void copyLayout(XWPFDocument srcDoc, XWPFDocument destDoc) {
        CTPageMar pgMar = srcDoc.getDocument().getBody().getSectPr().getPgMar();

        BigInteger bottom = pgMar.getBottom();
        BigInteger footer = pgMar.getFooter();
        BigInteger gutter = pgMar.getGutter();
        BigInteger header = pgMar.getHeader();
        BigInteger left = pgMar.getLeft();
        BigInteger right = pgMar.getRight();
        BigInteger top = pgMar.getTop();

        CTPageMar addNewPgMar = destDoc.getDocument().getBody().addNewSectPr().addNewPgMar();

        addNewPgMar.setBottom(bottom);
        addNewPgMar.setFooter(footer);
        addNewPgMar.setGutter(gutter);
        addNewPgMar.setHeader(header);
        addNewPgMar.setLeft(left);
        addNewPgMar.setRight(right);
        addNewPgMar.setTop(top);

        CTPageSz pgSzSrc = srcDoc.getDocument().getBody().getSectPr().getPgSz();

        BigInteger code = pgSzSrc.getCode();
        BigInteger h = pgSzSrc.getH();
        Enum orient = pgSzSrc.getOrient();
        BigInteger w = pgSzSrc.getW();

        CTPageSz addNewPgSz = destDoc.getDocument().getBody().addNewSectPr().addNewPgSz();

        addNewPgSz.setCode(code);
        addNewPgSz.setH(h);
        addNewPgSz.setOrient(orient);
        addNewPgSz.setW(w);
    }
}