All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pageseeder.docx.ant.ExportTask Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1999-2012 weborganic systems pty. ltd.
 */
package org.pageseeder.docx.ant;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.pageseeder.docx.util.Files;
import org.pageseeder.docx.util.XSLT;
import org.pageseeder.docx.util.ZipUtils;
import org.slf4j.Logger;

import javax.xml.transform.Templates;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * An ANT task to export a PageSeeder document to a Word document using the DOCX format.
 *
 * @author Christophe Lauret
 * @version 18 March 2014
 */
public final class ExportTask extends Task {

  /**
   * Used to prefix filenames of template images to avoid clashes with PSML images.
   */
  public static String MEDIA_PREFIX = "kwo5nu83zotp2-";

  /**
   * The PageSeeder documents to export.
   *
   * 

The source should point to the main PSML document. */ private File source; /** * The Word document to generate. */ private File destination; /** * The name of the working directory */ private File working; /** * The dotx file to use. */ private File dotx; /** * The configuration. */ private File config; /** * The media folder. */ private File media; /** * List of custom parameters specified that can be specified from the command-line */ private List params = new ArrayList<>(); // Set properties // ---------------------------------------------------------------------------------------------- /** * Set the source file: a PageSeeder document to export as DOCX. * * @param source The master document for document to export. */ public void setSrc(File source) { if (!(source.exists())) { throw new BuildException("the document " + source.getName() + " doesn't exist"); } if (source.isDirectory()) { throw new BuildException("the document " + source.getName() + " can't be a directory"); } this.source = source; } /** * Set the destination folder where PSML files should be stored. * * @param destination Where to store the PSML files. */ public void setDest(File destination) { if (destination.exists() && destination.isDirectory()) { throw new BuildException("if document DOCX exists, it must be a file, not " + destination); } this.destination = destination; } /** * Set DOTX template to use as a base. * * @param source The master document for document to export. */ public void setWordTemplate(File dotx) { if (!(dotx.exists())) { throw new BuildException("the Word template " + dotx.getName() + " doesn't exist"); } if (dotx.isDirectory()) { throw new BuildException("the document " + dotx.getName() + " can't be a directory"); } this.dotx = dotx; } /** * Set the working folder (optional). * * @param working The working folder. */ public void setWorking(File working) { if (working.exists() && !working.isDirectory()) { throw new BuildException("if working folder exists, it must be a directory"); } this.working = working; } /** * Set the configuration file (optional). * * @param config The configuration file. */ public void setConfig(File config) { if (!config.exists() || config.isDirectory()) { throw new BuildException("your configuration file must exist and be a file"); } this.config = config; } /** * Set the media folder (optional). * @param media The media folder. */ public void setMedia(File media) { if (!media.exists() || !media.isDirectory()) { throw new BuildException("your media folder must exist and be a directory"); } this.media = media; } /** * Create a parameter object and stores it in the list To be used by the XSLT transformation * *

This follows the ANT convention to allow the param element to be specified. * * @return The parameter object. */ public Parameter createParam() { Parameter param = new Parameter(); this.params.add(param); return param; } // Execute // ---------------------------------------------------------------------------------------------- @Override public void execute() throws BuildException { if (this.source == null) { throw new BuildException("Source presentation must be specified using 'src' attribute"); } // Defaulting working directory if (this.working == null) { String tmp = "antdocx-" + System.currentTimeMillis(); this.working = new File(System.getProperty("java.io.tmpdir"), tmp); } if (!this.working.exists()) { this.working.mkdirs(); } // Check parameters for (Parameter p : this.params) { if (p.getName() == null) { throw new BuildException("parameters must have a name"); } if (p.getName().startsWith("_")) { throw new BuildException("parameter names must not start with an underscore"); } } // The name of the source String name = this.source.getName(); if (name.endsWith(".psml")) { name = name.substring(0, name.length() - 5); } // Defaulting destination directory if (this.destination == null) { this.destination = new File(this.source.getParentFile(), name + ".docx"); log("Destination set to " + this.destination.getName()); } // Defaulting config file if (this.config == null) { // com.pageseeder.ant.docx.xslt.export.wpml-config.xml this.config = null; // TODO log("Using default wpml configuration for export"); } // 0. Ensure we have a word template to use if (this.dotx == null) { log("No DOTX specified, using default word temlate "); this.dotx = getBuiltinWordTemplate(this.working); } // 1. Let's unzip the dotx log("Extracting template: " + this.dotx.getName()); File dotx = new File(this.working, "dotx"); dotx.mkdirs(); ZipUtils.unzip(this.dotx, dotx); // 2. Sanity check log("Checking template"); File contentTypes = new File(dotx, "[Content_Types].xml"); File relationships = new File(dotx, "_rels/.rels"); if (!contentTypes.exists()) { throw new BuildException("Not a valid DOTX: unable to find [Content_Types].xml"); } if (!relationships.exists()) { throw new BuildException("Not a valid DOTX: unable to find _rels/.rels"); } // 3. Preparing the output File prepacked = new File(this.working, "prepacked"); prepacked.mkdirs(); ZipUtils.unzip(this.dotx, prepacked); File document = new File(prepacked, "word/document.xml"); Files.ensureDirectoryExists(document.getParentFile()); File mediaFolder = new File(prepacked, "word/media"); // for backward compatibility don't prefix when PSML images already copied to media folder String mediaPrefix = ""; // 4. (extra) copy everything from the media folder to prepacked folder if (this.media != null) { log("Copying media files"); if (!mediaFolder.exists()) { mediaFolder.mkdirs(); } // prefix template media files with a random string to avoid clashes with PSML images mediaPrefix = MEDIA_PREFIX; Files.renameFiles(mediaFolder, mediaPrefix); try { Files.copyDirectory(this.media, mediaFolder); } catch (IOException e) { log("Failed to copy media files: " + e.getMessage()); } } // 5. Unnest the files log("Unnesting"); Templates unnest = XSLT.getTemplatesFromResource("org/pageseeder/docx/xslt/export-unnest.xsl"); File sourceDocument = this.source; File newSourceDocument = new File(this.working, "unnested/document-unnested.psml"); newSourceDocument.getParentFile().mkdir(); Map noParameters = Collections.emptyMap(); Logger logger = AntLogger.newInstance(this); XSLT.transform(sourceDocument, newSourceDocument, unnest, noParameters, logger); // 6. Process the files log("Processing with XSLT"); // Parse templates Templates templates = XSLT.getTemplatesFromResource("org/pageseeder/docx/xslt/export.xsl"); // Initiate parameters Map parameters = new HashMap<>(); parameters.put("_outputfolder", prepacked.toURI().toString()); parameters.put("_dotxfolder", dotx.toURI().toString()); parameters.put("_docxfilename", this.destination.getName()); parameters.put("_mediaprefix", mediaPrefix); if (this.config != null) { parameters.put("_configfileurl", this.config.toURI().toString()); } // Add custom parameters for (Parameter p : this.params) { parameters.put(p.getName(), p.getValue()); } // Transform XSLT.transform(newSourceDocument, document, templates, parameters, logger); // 7. Move or Zip the generated content if (parameters.containsKey("expanded") && parameters.get("expanded").equals("true")) { log("Moving"); prepacked.renameTo(this.destination); // for backward compatibility } else if (parameters.containsKey("generate-processed-psml") && parameters.get("generate-processed-psml").equals("true")) { log("Copying processed PSML"); File newDestinationDocument = new File(this.destination.getParentFile() + "/document.xml"); try { Files.copy(document, newDestinationDocument); } catch (IOException e) { log("Failed to copy processed PSML: " + e.getMessage()); } this.destination.getParentFile().mkdirs(); ZipUtils.zip(prepacked, this.destination); } else { log("Zipping"); this.destination.getParentFile().mkdirs(); ZipUtils.zip(prepacked, this.destination); } } // Helpers // ---------------------------------------------------------------------------------------------- /** * Loads the built-in word template from the resource in classpath and saves it as a file. * * @param working The working folder where the template file should be loaded. * * @return a copy of the built-in template as a file */ private static File getBuiltinWordTemplate(File working) { File tmp = new File(working, "default.dotx"); try { ClassLoader loader = ExportTask.class.getClassLoader(); InputStream in = loader.getResourceAsStream("org/pageseeder/docx/resource/default.dotx"); try { FileOutputStream out = new FileOutputStream(tmp); try { final byte[] buffer = new byte[1024]; int n; while ((n = in.read(buffer)) != -1) { out.write(buffer, 0, n); } } finally { out.close(); } } finally { in.close(); } } catch (IOException ex) { throw new BuildException("Unable to extract default word template", ex); } return tmp; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy