Package org.docx4j.model.fields

Source Code of org.docx4j.model.fields.FieldUpdater

package org.docx4j.model.fields;

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

import javax.xml.transform.TransformerException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.docx4j.TraversalUtil;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.model.fields.docproperty.DocPropertyResolver;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.JaxbXmlPart;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.CTSimpleField;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.P;
import org.docx4j.wml.R;
import org.docx4j.wml.Text;

/**
* Refreshes the values of certain fields in the
* docx (currently DOCPROPERTY only).
*
* Do this whether they are simple or complex.
*
* This updates the docx.  If you don't want to do
* that, apply it to a clone instead.
*
* @author jharrop
*
*/
public class FieldUpdater {
 
  private static Logger log = LoggerFactory.getLogger(FieldUpdater.class);     
 
  WordprocessingMLPackage wordMLPackage;
  DocPropertyResolver docPropertyResolver;
 
  StringBuilder report = null;
 
  public FieldUpdater(WordprocessingMLPackage wordMLPackage) {
    this.wordMLPackage = wordMLPackage;
//    docPropsCustomPart = wordMLPackage.getDocPropsCustomPart();
    docPropertyResolver = new DocPropertyResolver(wordMLPackage);
  }

  public void update(boolean processHeadersAndFooters) throws Docx4JException {

    report = new StringBuilder();
   
    updatePart(wordMLPackage.getMainDocumentPart() );

    if (processHeadersAndFooters) {
     
      RelationshipsPart rp = wordMLPackage.getMainDocumentPart().getRelationshipsPart();
      for ( Relationship r : rp.getJaxbElement().getRelationship()  ) {
       
        if (r.getType().equals(Namespaces.HEADER)
            || r.getType().equals(Namespaces.FOOTER)) {
         
          JaxbXmlPart part = (JaxbXmlPart)rp.getPart(r);
         
          report.append("\n" + part.getPartName() + "\n");
                   
          log.debug("\n" + part.getPartName() + "\n");
          updatePart(part );
//            performOnInstance(
//                ((ContentAccessor)part).getContent() );
         
        }     
      } 
    } 
   
    log.info(report.toString());
  }
 
  public void updatePart(JaxbXmlPart part) throws Docx4JException {

    updateSimple(part);
    updateComplex(part);
  }
 
  public void updateSimple(JaxbXmlPart part) throws Docx4JException {
   
    FldSimpleModel fsm = new FldSimpleModel(); //gets reused
    List contentList = ((ContentAccessor)part).getContent();
    WordprocessingMLPackage wmlPackage = (WordprocessingMLPackage)part.getPackage();
   
    // find fields
    SimpleFieldLocator fl = new SimpleFieldLocator();
    new TraversalUtil(contentList, fl);
   
    report.append("\n\nSimple Fields in " + part.getPartName() + "\n");
    report.append("============= \n");
    report.append("Found " + fl.simpleFields.size() + " simple fields \n ");
   
    for( CTSimpleField simpleField : fl.simpleFields ) {
     
      //System.out.println(XmlUtils.marshaltoString(simpleField, true, true));
//      System.out.println(simpleField.getInstr());
     
      if ("DOCPROPERTY".equals(FormattingSwitchHelper.getFldSimpleName(simpleField.getInstr()))) {
        //only parse those fields that get processed
        try {
          fsm.build(simpleField.getInstr());
        } catch (TransformerException e) {
          e.printStackTrace();
        }
       
        String key = fsm.getFldParameters().get(0);
       
        String val;
        try {
          val = (String) docPropertyResolver.getValue(key);
        } catch (FieldValueException e) {
          report.append( simpleField.getInstr() + "\n");
          report.append( key + " -> NOT FOUND! \n")
          continue;
        }
       
        if (val==null) {
         
          report.append( simpleField.getInstr() + "\n");
          report.append( key + " -> NOT FOUND! \n")
         
        } else {
              //docPropsCustomPart.getProperty(key);
  //        System.out.println(val);
          val = FormattingSwitchHelper.applyFormattingSwitch(wmlPackage, fsm, val);
  //        System.out.println("--> " + val);
          report.append( simpleField.getInstr() + "\n");
          report.append( "--> " + val + "\n");
         
          R r=null;
          if (simpleField.getInstr().toUpperCase().contains("MERGEFORMAT")) {         
            // find the first run and use the formatting of that
            r = getFirstRun(simpleField.getContent());         
          }
          if (r==null) {
            r = Context.getWmlObjectFactory().createR();
          } else {
            r.getContent().clear();
          }
          simpleField.getContent().clear()
          simpleField.getContent().add(r);
          Text t = Context.getWmlObjectFactory().createText();
          t.setValue(val);
          // t.setSpace(value) //TODO
          r.getContent().add(t);
         
  //        System.out.println(XmlUtils.marshaltoString(simpleField, true, true));
        }
       
      } else {
       
        report.append("Ignoring " + simpleField.getInstr() + "\n");
       
      }
    }
   
  }
 
  private R getFirstRun(List<Object> content) {
   
    for (Object o : content) {
      if (o instanceof R) return (R)o;
    }
    return null;
  }

  public void updateComplex(JaxbXmlPart part) throws Docx4JException {
   
    FldSimpleModel fsm = new FldSimpleModel(); //gets reused
    List contentList = ((ContentAccessor)part).getContent();
    WordprocessingMLPackage wmlPackage = (WordprocessingMLPackage)part.getPackage();
   
    ComplexFieldLocator fl = new ComplexFieldLocator();
    new TraversalUtil(contentList, fl);
   
    report.append("\n Complex Fields in "+ part.getPartName() + "\n");
    report.append("============== \n");
   
    report.append("Found " + fl.getStarts().size() + " fields \n");
   
   
    // canonicalise and setup fieldRefs
    List<FieldRef> fieldRefs = new ArrayList<FieldRef>();
    for( P p : fl.getStarts() ) {
      int index;
      if (p.getParent() instanceof ContentAccessor) {
        index = ((ContentAccessor)p.getParent()).getContent().indexOf(p);
        P newP = FieldsPreprocessor.canonicalise(p, fieldRefs);
//        log.debug("NewP length: " + newP.getContent().size() );
        ((ContentAccessor)p.getParent()).getContent().set(index, newP);
      } else if (p.getParent() instanceof java.util.List) {
        // This does happen!
        index = ((java.util.List)p.getParent()).indexOf(p);
        P newP = FieldsPreprocessor.canonicalise(p, fieldRefs);
//        log.debug("NewP length: " + newP.getContent().size() );
        ((java.util.List)p.getParent()).set(index, newP);       
      } else {
        throw new Docx4JException ("Unexpected parent: " + p.getParent().getClass().getName() );
      }
    }
   
    // Populate
    for (FieldRef fr : fieldRefs) {
     
      if ("DOCPROPERTY".equals(fr.getFldName())) {
       
        String instr = extractInstr(fr.getInstructions());
        try {
          fsm.build(instr);
        } catch (TransformerException e) {
          e.printStackTrace();
        }

        String key = fsm.getFldParameters().get(0);
        String val = (String) docPropertyResolver.getValue(key);
        try {
          val = (String) docPropertyResolver.getValue(key);
        } catch (FieldValueException e) {
          report.append( instr + "\n");
          report.append( key + " -> NOT FOUND! \n")
          continue;
        }
       
        if (val==null) {
         
          report.append( instr + "\n");
          report.append( key + " -> NOT FOUND! \n");
         
        } else {
       
  //        System.out.println(val);
          val = FormattingSwitchHelper.applyFormattingSwitch(wmlPackage, fsm, val);
  //        System.out.println("--> " + val);
          report.append( instr + "\n");
          report.append( "--> " + val + "\n");
 
          fr.setResult(val);
         
  //        // If doing an actual mail merge, the begin-separate run is removed, as is the end run
  //        fr.getParent().getContent().remove(fr.getBeginRun());
  //        fr.getParent().getContent().remove(fr.getEndRun());
         
//          System.out.println(XmlUtils.marshaltoString(
//              fr.getParent(), true, true));
        }       
      } else {
        report.append("Ignoring " + fr.getFldName() + "\n");       
      }
    } 
  }
 
  private String extractInstr(List<Object> instructions) {
    // For DOCPROPERTY, expect the list to contain a simple string
   
    if (instructions.size()!=1) {
      log.error("TODO DOCPROPERTY 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;
    }
  }
 
  /**
   * @param args
   * @throws Docx4JException
   */
  public static void main(String[] args) throws Docx4JException {

    WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(
        new java.io.File(
            System.getProperty("user.dir") + "/aq1.docx"));
   
    FieldUpdater fu = new FieldUpdater(wordMLPackage);
    fu.update(true);
   
    System.out.println(XmlUtils.marshaltoString(wordMLPackage.getMainDocumentPart().getJaxbElement(), true, true));
   
  }

}
TOP

Related Classes of org.docx4j.model.fields.FieldUpdater

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.