blob: 7dbe4ecb5a7f6fcdb61c11460a7bf2d689edb817 [file] [log] [blame]
/*****************************************************************************
* (c) Copyright 2016 Telefonaktiebolaget LM Ericsson
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Antonio Campesino (Ericsson) antonio.campesino.robles@ericsson.com - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.gendoc.services.pptx;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.xpath.XPathExpressionException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.gendoc.document.parser.documents.XMLParser;
import org.eclipse.gendoc.document.parser.pptx.PPTXDocument;
import org.eclipse.gendoc.document.parser.pptx.PPTXHelper;
import org.eclipse.gendoc.document.parser.pptx.XPathPptxUtils;
import org.eclipse.gendoc.documents.AdditionalResourceService;
import org.eclipse.gendoc.documents.FileRunnable;
import org.eclipse.gendoc.documents.IAdditionalResourceService;
import org.eclipse.gendoc.documents.IDocumentManager;
import org.eclipse.gendoc.documents.IDocumentService;
import org.eclipse.gendoc.documents.IImageService;
import org.eclipse.gendoc.documents.MimeTypes;
import org.eclipse.gendoc.documents.ResourceRunnable;
import org.eclipse.gendoc.services.GendocServices;
import org.eclipse.gendoc.services.ILogger;
import org.eclipse.gendoc.services.exception.AdditionalResourceException;
import org.eclipse.gendoc.services.utils.DefaultImageExtensionUtils;
import org.eclipse.gendoc.services.pptx.PPTXDocumentService;
import org.w3c.dom.Element;
public class PPTXAdditionalResourceService extends AdditionalResourceService implements IAdditionalResourceService {
private IImageService imageService;
private List<Element> relationshipsToAdd;
protected Map<String, String> externalChunkMap;
public PPTXAdditionalResourceService() {
super();
relationshipsToAdd = new ArrayList<Element>();
externalChunkMap = new LinkedHashMap<String, String>();
imageService = new PPTXImageService();
}
@Override
public IImageService getImageService() {
return imageService;
}
@Override
public String includeFile(String filePath) {
String id = generateUniqueId();
externalChunkMap.put(id, filePath);
// Add file extension to extensions list
fileExtensions.add(Path.fromOSString(filePath).getFileExtension());
return id;
}
@Override
public void includeExtensions(Set<String> fileExt) {
fileExtensions.addAll(fileExt);
}
@Override
public void addAdditionalResourcesToDocument() throws AdditionalResourceException {
String mediaLoc = getResourceFolder();
IDocumentManager docManager = GendocServices.getDefault().getService(IDocumentManager.class);
PPTXDocument pptxDocument = (PPTXDocument)docManager.getDocTemplate();
PPTXDocumentService documentService = GendocServices.getDefault()
.getService(IDocumentService.class);
// Get directory "media" and add it if not present
File mediaDir = new File(mediaLoc);
if (!mediaDir.exists()) {
mediaDir.mkdir();
}
// Add images resources to document
addImagesResourcesToDocument(mediaLoc);
// Add external file resources to document
addExternalResourcesToDocument(mediaLoc);
// Add mappings between images and files
//String relsLocation = addRelationShips(unzipLoc);
String relsLocation = SEPARATOR + "ppt" + SEPARATOR + "slides" + SEPARATOR + "_rels" + SEPARATOR;
// Add mapping files for each document XML (document.xml, headers,
// footers)
addRelationShipFiles(pptxDocument, relsLocation);
// Modify file with content types [Content_Types].xml to add unknown
// file extensions
modifyContentTypes(pptxDocument);
}
public String addRunnableResourceToDocument(String mediaLoc,
String diagramKey) throws AdditionalResourceException {
if (runnableMap.get(diagramKey) == null) {
throw new AdditionalResourceException("Image with id '"
+ diagramKey + "' cannot be found.");
}
// Get runnableResource
ResourceRunnable runnable = runnableMap.get(diagramKey);
String extension = getFileExtensionFromRunnable(runnable);
// Run the resource
runnable.run(diagramKey, getResourceFolder());
// add relationship in drawing*.xml.rels
relationshipsToAdd.add(newImageRelationship(diagramKey, diagramKey + "."+ extension));
fileExtensions.add(extension);
return getResourceFolder() + SEPARATOR + diagramKey + "." + extension;
}
@Override
protected String getRelativeResourceFolder() {
return "ppt" + SEPARATOR + "media";
}
private void addImagesResourcesToDocument(String mediaLoc)
throws AdditionalResourceException {
// For each image
for (String imageKey : imagesMap.keySet()) {
// add image as file in the media directory
File imageFile = new File(imagesMap.get(imageKey));
// Extract and normalize file name
String imageLink = imageKey
+ "."
+ Path.fromOSString(imageFile.getAbsolutePath())
.getFileExtension();
try {
copyImage(imageFile, mediaLoc + SEPARATOR + imageLink);
} catch (IOException e) {
throw new AdditionalResourceException("File '"
+ imageFile.getAbsolutePath() + "'cannot be copied.", e);
}
// add relationship in document.xml.rels
relationshipsToAdd.add(newImageRelationship(imageKey, imageLink));
if (!imageFile.exists()) {
throw new AdditionalResourceException(
"An image cannot be generated and has been replaced by a red cross. Cause: No image found at location:"
+ imageFile.getAbsolutePath());
}
}
}
// TODO: Check if external docs can be inserted.
private void addExternalResourcesToDocument(String mediaLoc) throws AdditionalResourceException {
/* for (String key : externalChunkMap.keySet()) {
// add external file as file in the media directory
File file = new File(externalChunkMap.get(key));
// Extract file
String externalLink = key
+ "."
+ Path.fromOSString(file.getAbsolutePath())
.getFileExtension();// normalizeString(getFileName(externalChunkMap.get(key)));
try {
copyFile(file, mediaLoc + SEPARATOR + externalLink);
} catch (IOException e) {
throw new AdditionalResourceException("File '"
+ file.getAbsolutePath() + "'cannot be copied.", e);
}
// add relationship in document.xml.rels
relationShipsToAdd.append(newExternalChunkRelationship(key,
externalLink));
if (!file.exists()) {
throw new AdditionalResourceException(
"An external file cannot be generated. Cause: No file found at location:"
+ file.getAbsolutePath());
}
}*/
}
private void addRelationShipFiles(PPTXDocument pptxDocument, String relsLocation)
throws AdditionalResourceException {
if (relationshipsToAdd == null)
return;
ILogger logger = GendocServices.getDefault().getService(ILogger.class);
// Get Word directory
File wordDir = new File(pptxDocument.getUnzipLocationDocumentFile()+
File.separator+relsLocation+File.separator+"..");
if (!wordDir.isDirectory()) {
return;
}
String[] fileNames = wordDir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
name = name.toLowerCase();
return name.startsWith("slide") && name.endsWith(".xml");
}
});
try {
// Add new relationships to all headers and footers
for (String fileName : fileNames) {
String relpath = relsLocation+ fileName + ".rels";
XMLParser relParser = pptxDocument.getSubdocument(relpath);
if (relParser == null) {
relParser = pptxDocument.createSubdocument(relpath, "<?xml version=\"1.0\" encoding=\"windows-1250\"?> "
+ "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"/>");
}
try {
for (Element relToAdd : relationshipsToAdd) {
if (XPathPptxUtils.INSTANCE.evaluateNode(relParser.getDocument(), "/rel:Relationships/rel:Relationship[@Id='"+
relToAdd.getAttribute("Id")+"']") != null)
continue;
relParser.getDocument().getDocumentElement().appendChild(
relParser.getDocument().importNode(relToAdd, true));
}
} catch (XPathExpressionException e) {
throw new IllegalArgumentException(e);
}
}
} catch (IOException e) {
logger.log(
"Mapping files for headers and footers are not copied properly. Some images in headers and "
+ "footers can be missing.",
IStatus.INFO);
}
}
private void modifyContentTypes(PPTXDocument pptxDocument)
throws AdditionalResourceException {
XMLParser ctParser = pptxDocument.getSubdocument("/[Content_Types].xml");
try {
for (String extension : fileExtensions) {
if (XPathPptxUtils.INSTANCE.evaluateNode(ctParser.getDocument(),
"/ct:Types/ct:Default[@Extension='"+extension+"']") != null)
continue;
Element extEl = ctParser.getDocument().createElementNS(
PPTXHelper.CONTENT_TYPES_NAMESPACE, "Default");
extEl.setAttribute("ContentType", MimeTypes.getMimeTypefromExtension(extension));
extEl.setAttribute("Extension", extension);
ctParser.getDocument().getDocumentElement().insertBefore(
extEl, ctParser.getDocument().getDocumentElement().getFirstChild());
}
} catch (Exception e) {
throw new AdditionalResourceException(e);
}
}
private Element newImageRelationship(String imageKey, String imageLink) {
try {
return (Element)XPathPptxUtils.INSTANCE.parserXmlFragment("<rel:Relationship Id=\""
+ imageKey
+ "\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image\" Target=\"../media/"
+ imageLink + "\"/>");
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
private String newExternalChunkRelationship(String key, String target) {
return "<Relationship Id=\""
+ key
+ "\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk\" Target=\"../media/"
+ target + "\"/>";
}
private String getFileExtensionFromRunnable(ResourceRunnable runnable) {
if (runnable instanceof FileRunnable) {
return ((FileRunnable) runnable).getFileExtension();
}
return DefaultImageExtensionUtils.getDefaultImageExtension();
}
}