org.docx4j.template.utils.WMLPackageUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.docx4j.template.utils.WMLPackageUtils.java

Source

/*
 * Copyright (c) 2018, vindell (https://github.com/vindell).
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.docx4j.template.utils;

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.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.contenttype.ContentType;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.AlternativeFormatInputPart;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.CTAltChunk;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.P;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Text;
import org.docx4j.wml.Tr;

/**
 * TODO
 * @author <a href="https://github.com/vindell">vindell</a>
 */
@SuppressWarnings("unchecked")
public class WMLPackageUtils {

    protected static String CONTENT_TYPE = "";

    /*
     * ??word?Word??template.docx?word
     * ??docx4j?????
     */
    public static WordprocessingMLPackage getWMLPackageTemplate(String filepath)
            throws Docx4JException, FileNotFoundException {
        WordprocessingMLPackage template = WordprocessingMLPackage.load(new FileInputStream(new File(filepath)));
        return template;
    }

    public static <T> List<T> getChildrenElements(Object source, Class<T> targetClass) {
        List<T> result = new ArrayList<T>();
        //?
        Object target = XmlUtils.unwrap(source);
        //if (target.getClass().equals(targetClass)) {
        if (targetClass.isAssignableFrom(target.getClass())) {
            result.add((T) target);
        } else if (target instanceof ContentAccessor) {
            List<?> children = ((ContentAccessor) target).getContent();
            //if (children.getClass().equals(targetClass)) {
            if (targetClass.isAssignableFrom(children.getClass())) {
                result.add((T) children);
            }
        }
        return result;
    }

    /*
     * Java?Docx4J API??wordDocx4J???
     * ???????JAXB
     * ?????????? 
     */
    public static <T> List<T> getTargetElements(Object source, Class<T> targetClass) {
        List<T> result = new ArrayList<T>();
        //?
        Object target = XmlUtils.unwrap(source);
        //if (target.getClass().equals(targetClass)) {
        if (targetClass.isAssignableFrom(target.getClass())) {
            result.add((T) target);
        } else if (target instanceof ContentAccessor) {
            List<?> children = ((ContentAccessor) target).getContent();
            for (Object child : children) {
                result.addAll(getTargetElements(child, targetClass));
            }
        }
        return result;
    }

    /*
     * ?????SJ_EX1???name???
     * docx4jorg.docx4j.wml.Text??????? 
     */
    public static void replacePlaceholder(WordprocessingMLPackage template, String name, String placeholder) {
        //?Text
        List<Text> texts = getTargetElements(template.getMainDocumentPart(), Text.class);
        //Text?
        for (Text text : texts) {
            Text textElement = (Text) text;
            if (textElement.getValue().equals(placeholder)) {
                textElement.setValue(name);
            }
        }
    }

    public static void writeDocxToStream(WordprocessingMLPackage template, String target)
            throws IOException, Docx4JException {
        File f = new File(target);
        template.save(f);
    }

    /*
     *  ??
       ????????????????????Text???????Docx4j??
       ???
           
      ???
      ??
      ???
      ??
         
     * ******************************************************************
     */
    public static void replaceParagraph(String placeholder, String textToAdd, WordprocessingMLPackage template,
            ContentAccessor addTo) {
        // 1. get the paragraph  
        List<P> paragraphs = getTargetElements(template.getMainDocumentPart(), P.class);
        P toReplace = null;
        for (P p : paragraphs) {
            List<Text> texts = getTargetElements(p, Text.class);
            for (Text 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 (int i = 0; i < as.length; i++) {
            String ptext = as[i];

            // 3. copy the found paragraph to keep styling correct  
            P copy = (P) XmlUtils.deepCopy(toReplace);

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

            // add the paragraph to the document  
            addTo.getContent().add(copy);
        }

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

    }

    /*
     * ?????map??addRowToTable  getTemplateTable?? 
     */
    public static Tbl getTable(List<Tbl> tables, String placeholder) throws Docx4JException {
        for (Iterator<Tbl> iterator = tables.iterator(); iterator.hasNext();) {
            Tbl tbl = iterator.next();
            //?table?text
            List<Text> textElements = getTargetElements(tbl, Text.class);
            for (Text text : textElements) {
                Text textElement = (Text) text;
                //
                if (textElement.getValue() != null && textElement.getValue().equals(placeholder)) {
                    return (Tbl) tbl;
                }
            }
        }
        return null;
    }

    public static void replaceTable(String[] placeholders, List<Map<String, String>> textToAdd,
            WordprocessingMLPackage template) throws Docx4JException, JAXBException {
        List<Tbl> tables = getTargetElements(template.getMainDocumentPart(), Tbl.class);

        // 1. find the table  
        Tbl tempTable = getTable(tables, placeholders[0]);
        List<Tr> rows = getTargetElements(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);

            for (Map<String, String> replacements : textToAdd) {
                // 2 and 3 are done in this method  
                addRowToTable(tempTable, templateRow, replacements);
            }

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

    public static void addRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> replacements) {
        Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
        List<?> textElements = getTargetElements(workingRow, Text.class);
        for (Object object : textElements) {
            Text text = (Text) object;
            String replacementValue = (String) replacements.get(text.getValue());
            if (replacementValue != null)
                text.setValue(replacementValue);
        }

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

    public static InputStream mergeDocx(final List<InputStream> streams) throws Docx4JException, IOException {

        WordprocessingMLPackage target = null;
        final File generated = File.createTempFile("generated", ".docx");

        int chunkId = 0;
        Iterator<InputStream> it = streams.iterator();
        while (it.hasNext()) {
            InputStream is = it.next();
            if (is != null) {
                if (target == null) {
                    // Copy first (master) document   
                    OutputStream os = new FileOutputStream(generated);
                    os.write(IOUtils.toByteArray(is));
                    os.close();
                    target = WordprocessingMLPackage.load(generated);
                } else {
                    // Attach the others (Alternative input parts)   
                    insertDocx(target.getMainDocumentPart(), IOUtils.toByteArray(is), chunkId++);
                }
            }
        }

        if (target != null) {
            target.save(generated);
            return new FileInputStream(generated);
        } else {
            return null;
        }
    }

    // ?   
    private static void insertDocx(MainDocumentPart main, byte[] bytes, int chunkId) {
        try {
            AlternativeFormatInputPart afiPart = new AlternativeFormatInputPart(
                    new PartName("/part" + chunkId + ".docx"));
            afiPart.setContentType(new ContentType(CONTENT_TYPE));
            afiPart.setBinaryData(bytes);
            Relationship altChunkRel = main.addTargetPart(afiPart);

            CTAltChunk chunk = Context.getWmlObjectFactory().createCTAltChunk();
            chunk.setId(altChunkRel.getId());

            main.addObject(chunk);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
      * ??. 
      * @param file  ?? 
      * @return      ?? 
      * @throws FileNotFoundException 
      * @throws IOException 
      */
    public static byte[] imageToByteArray(File file) throws FileNotFoundException, IOException {
        InputStream is = new FileInputStream(file);
        long length = file.length();
        // ?long, ?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;
        }
        // ?  
        if (offset < bytes.length) {
            System.out.println("Could not completely read file " + file.getName());
        }
        is.close();
        return bytes;
    }

}