MultipleRowTableRenderPolicy.java 7.26 KB
package com.lhcredit.common.utils.poi;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.RenderPolicy;
import com.deepoove.poi.render.compute.EnvModel;
import com.deepoove.poi.render.compute.RenderDataCompute;
import com.deepoove.poi.render.processor.DocumentProcessor;
import com.deepoove.poi.render.processor.EnvIterator;
import com.deepoove.poi.resolver.TemplateResolver;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.MetaTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.ReflectionUtils;
import com.deepoove.poi.util.TableTools;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
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.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;

public class MultipleRowTableRenderPolicy implements RenderPolicy {
    private static final String DEFAULT_MULTIPLE_PREFIX = "$(";
    private static final String DEFAULT_MULTIPLE_SUFFIX = ")";
    private static final String DEFAULT_PREFIX = "[";
    private static final String DEFAULT_SUFFIX = "]";
    private static final int DEFAULT_MULTIPLE_ROW_NUM = 1;
    private final String regex;
    private final String multiplePrefix;
    private final String multipleSuffix;
    private final String prefix;
    private final String suffix;

    public MultipleRowTableRenderPolicy() {
        this("$(", ")", "[", "]");
    }

    public MultipleRowTableRenderPolicy(String prefix, String suffix) {
        this("$(", ")", prefix, suffix);
    }

    private MultipleRowTableRenderPolicy(String multiplePrefix, String multipleSuffix, String prefix, String suffix) {
        this.regex = "\\$\\([0-9]+\\)";
        this.multiplePrefix = multiplePrefix;
        this.multipleSuffix = multipleSuffix;
        this.prefix = prefix;
        this.suffix = suffix;
    }

    public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
        try {
            RunTemplate runTemplate = this.cast2runTemplate(eleTemplate);
            XWPFRun run = runTemplate.getRun();
            this.checkTargetIsTable(run, "Processing [" + runTemplate.getTagName() + "] failed, the target content is not a table");
            XWPFTableCell tagCell = (XWPFTableCell)((XWPFParagraph)run.getParent()).getBody();
            XWPFTable table = tagCell.getTableRow().getTable();
            run.setText("", 0);
            TemplateResolver resolver = new TemplateResolver(template.getConfig().copy(this.prefix, this.suffix));
            int position = this.getRowIndex(tagCell.getTableRow());
            List<XWPFTableRow> tempRows = this.getAllTemplateRow(table, position);
            if (null != data && data instanceof Iterable) {
                XWPFTableRow firstTempRow = (XWPFTableRow)tempRows.get(0);
                Iterator<?> dataIt = ((Iterable)data).iterator();
                boolean hasNextData = dataIt.hasNext();

                for(int index = 0; hasNextData; ++index) {
                    Object dt = dataIt.next();
                    hasNextData = dataIt.hasNext();
                    Iterator<XWPFTableRow> rowTempIt = tempRows.iterator();

                    for(boolean hasNextTempRow = rowTempIt.hasNext(); hasNextTempRow; ++position) {
                        XWPFTableRow tempRow = (XWPFTableRow)rowTempIt.next();
                        hasNextTempRow = rowTempIt.hasNext();
                        if (!table.addRow(tempRow, position)) {
                            throw new RenderException("创建新的表格行失败");
                        }

                        XmlCursor newCursor = firstTempRow.getCtRow().newCursor();
                        newCursor.toPrevSibling();
                        XmlObject object = newCursor.getObject();
                        XWPFTableRow newRow = new XWPFTableRow((CTRow)object, table);
                        newRow.getCtRow().set(object);
                        this.setTableRow(table, newRow, position);
                        List<XWPFTableCell> cells = newRow.getTableCells();
                        RenderDataCompute dataCompute = template.getConfig().getRenderDataComputeFactory().newCompute(EnvModel.of(dt, EnvIterator.makeEnv(index, hasNextData || hasNextTempRow)));
                        cells.forEach((tableCell) -> {
                            List<MetaTemplate> metaTemplates = resolver.resolveBodyElements(tableCell.getBodyElements());
                            (new DocumentProcessor(template, resolver, dataCompute)).process(metaTemplates);
                        });
                    }
                }
            }

            this.removeTableRow(table, position, tempRows.size());
        } catch (Exception var24) {
            throw new RenderException("failed to render table multi-row template", var24);
        }
    }

    protected List<XWPFTableRow> getAllTemplateRow(XWPFTable table, int startIndex) {
        List<XWPFTableRow> rows = table.getRows();
        int tempRowNum = 1;
        String text = ((XWPFTableRow)rows.get(startIndex)).getCell(0).getText();
        Matcher matcher = Pattern.compile("\\$\\([0-9]+\\)").matcher(text);
        if (matcher.find()) {
            String rowNumText = matcher.group(0);
            tempRowNum = Integer.parseInt(rowNumText.replace(this.multiplePrefix, "").replace(this.multipleSuffix, ""));
            List<XWPFParagraph> paragraphs = ((XWPFTableRow)rows.get(startIndex)).getCell(0).getParagraphs();
            ((XWPFRun)((XWPFParagraph)paragraphs.get(0)).getRuns().get(0)).setText(text.replace(rowNumText, ""), 0);

            for(int i = 1; i < ((XWPFParagraph)paragraphs.get(0)).getRuns().size(); ++i) {
                ((XWPFRun)((XWPFParagraph)paragraphs.get(0)).getRuns().get(i)).setText("", 0);
            }
        }

        return new Vector(rows.subList(startIndex, startIndex + tempRowNum));
    }

    protected void removeTableRow(XWPFTable table, int startIndex, int size) {
        for(int i = 0; i < size; ++i) {
            table.removeRow(startIndex);
        }

    }

    protected RunTemplate cast2runTemplate(MetaTemplate template) {
        if (!(template instanceof RunTemplate)) {
            throw new ClassCastException("type conversion failed, template is not of type RunTemplate");
        } else {
            return (RunTemplate)template;
        }
    }

    protected void checkTargetIsTable(XWPFRun run, String message) {
        if (Objects.isNull(run) || !TableTools.isInsideTable(run)) {
            throw new IllegalStateException(message);
        }
    }

    protected void setTableRow(XWPFTable table, XWPFTableRow row, int pos) {
        List<XWPFTableRow> rows = (List)ReflectionUtils.getValue("tableRows", table);
        rows.set(pos, row);
        table.getCTTbl().setTrArray(pos, row.getCtRow());
    }

    protected int getRowIndex(XWPFTableRow row) {
        List<XWPFTableRow> rows = row.getTable().getRows();
        return rows.indexOf(row);
    }
}