Package org.docx4j.model.datastorage.migration

Source Code of org.docx4j.model.datastorage.migration.FromMergeFields

package org.docx4j.model.datastorage.migration;

import java.util.ArrayList;
import java.util.List;

import org.docx4j.TraversalUtil;
import org.docx4j.XmlUtils;
import org.docx4j.model.fields.ComplexFieldLocator;
import org.docx4j.model.fields.FieldRef;
import org.docx4j.model.fields.FieldsPreprocessor;
import org.docx4j.openpackaging.io.SaveToZipFile;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.P;
import org.docx4j.wml.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This class will help you to migrate
* from MERGEFIELDs
* to use of content control data bindings.
*
* After migrating, you'll be able to
* use the OpenDoPE authoring tool to
* add repeats, conditionals, and other
* OpenDoPE features, if you need them.
*
* Limitations: this first version
* operates only on the main document part
* (ie it won't process variables in
*  headers/footers, footnotes/endnotes,
*  or comments)
* @author jharrop
* @since 3.0.0
*/
public class FromMergeFields extends AbstractMigrator {
 
  private static Logger log = LoggerFactory.getLogger(FromMergeFields.class);
 
  public WordprocessingMLPackage migrate(WordprocessingMLPackage pkgIn) throws Exception {
   
    // TODO - test that OpenDoPE parts aren't already present
    // or if they are, that this docx is using our answer format
    // (since only that format is supported here)
   
    // Clone it
    WordprocessingMLPackage pkgOut = (WordprocessingMLPackage)pkgIn.clone();
       
    // Create the CustomXML parts
    createParts(pkgOut);
   
    FieldsPreprocessor.complexifyFields(pkgOut.getMainDocumentPart() );
    log.debug("complexified: "
        + XmlUtils.marshaltoString(pkgOut.getMainDocumentPart().getJaxbElement(), true));
   
    // find fields
    ComplexFieldLocator fl = new ComplexFieldLocator();
    new TraversalUtil(pkgOut.getMainDocumentPart().getContent(), fl);
    log.info("Found " + fl.getStarts().size() + " fields ");
   
   
    // canonicalise and setup fieldRefs
    List<FieldRef> fieldRefs = new ArrayList<FieldRef>();
    for( P p : fl.getStarts() ) {
      int index = ((ContentAccessor)p.getParent()).getContent().indexOf(p);
      P newP = FieldsPreprocessor.canonicalise(p, fieldRefs);
      ((ContentAccessor)p.getParent()).getContent().set(index, newP);
     
      /*
       *   <w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:ns23="http://schemas.openxmlformats.org/schemaLibrary/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math">
            <w:r>
              <w:t xml:space="preserve">Hallo, lower </w:t>
            </w:r>
            <w:r>
              <w:rPr>
                <w:noProof/>
              </w:rPr>
              <w:fldChar w:fldCharType="begin"/>
              <w:instrText xml:space="preserve"> MERGEFIELD  kundenname  \* MERGEFORMAT  </w:instrText>
              <w:fldChar w:fldCharType="separate"/>
            </w:r>
            <w:r>
              <w:rPr>
                <w:noProof/>
              </w:rPr>
              <w:t>«Kundenname»</w:t>
            </w:r>
            <w:r/>
            <w:r>
              <w:fldChar w:fldCharType="end"/>
            </w:r>
          </w:p>
       */
    }
   
    // Populate
    for (FieldRef fr : fieldRefs) {
     
      if ( fr.getFldName().equals("MERGEFIELD") ) {
        String instr = extractInstr(fr.getInstructions() );

        // eg <w:instrText xml:space="preserve"> MERGEFIELD  Kundenstrasse \* MERGEFORMAT </w:instrText>
        // or <w:instrText xml:space="preserve"> MERGEFIELD  Kundenstrasse</w:instrText>
       
        String tmp = instr.substring( instr.indexOf("MERGEFIELD") + 10);
        tmp = tmp.trim();
        String key  = tmp.indexOf(" ") >-1 ? tmp.substring(0, tmp.indexOf(" ")) : tmp ;
        log.info("Key: '" + key + "'");
               
        // Remove the field related runs
        int end = fr.getParent().getContent().indexOf(fr.getEndRun());
        int begin = fr.getParent().getContent().indexOf(fr.getBeginRun());
        for (int i = end; i>=begin; i--) {
          fr.getParent().getContent().remove(i);
        }
       
        // Now add a content control
        List<Object> replacementContent = new ArrayList<Object>();
        createContentControl(null, replacementContent, key)
       
        fr.getParent().getContent().addAll(begin, replacementContent);
       
//        System.out.println(XmlUtils.marshaltoString(
//            fr.getParent(), true, true));
       
      }
    }
       
    return pkgOut;
  }
 
  private static String extractInstr(List<Object> instructions) {
    // For MERGEFIELD, expect the list to contain a simple string
   
    if (instructions.size()!=1) {
      log.error("TODO MERGEFIELD field contained complex instruction");
      return null;
    }
   
    Object o = XmlUtils.unwrap(instructions.get(0));
    if (o instanceof Text) {
      return ((Text)o).getValue();
    } else {
      log.error("TODO: extract field name from " + o.getClass().getName() );
      log.error(XmlUtils.marshaltoString(instructions.get(0), true, true) );
      return null;
    }
  }
 
//  public static boolean isMergeField(String type) {
//   
//    if (type.contains("MERGEFIELD")) {
//      return true;
//    } else {
//      return false;
//    }
//  }

  /**
   * @param args
   * @throws Exception
   */
  public static void main(String[] args) throws Exception {

    String inputfilepath = System.getProperty("user.dir")
                  + "/TEST1.docx";

    String outputfilepath = System.getProperty("user.dir")
        + "/OUT_TEST1.docx";

    WordprocessingMLPackage pkgIn = WordprocessingMLPackage.load(new java.io.File(inputfilepath));
   
    FromMergeFields migrator = new FromMergeFields();
    WordprocessingMLPackage pkgOut = migrator.migrate(pkgIn);
   
    SaveToZipFile saver = new SaveToZipFile(pkgOut);
    saver.save(outputfilepath);
   
  }

}
TOP

Related Classes of org.docx4j.model.datastorage.migration.FromMergeFields

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.