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

prerna.reactor.export.ToPPTReactor Maven / Gradle / Ivy

The newest version!
package prerna.reactor.export;

import java.awt.Rectangle;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.util.Units;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureData;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;

import prerna.auth.User;
import prerna.auth.utils.AbstractSecurityUtils;
import prerna.auth.utils.SecurityQueryUtils;
import prerna.om.InsightFile;
import prerna.om.ThreadStore;
import prerna.reactor.AbstractReactor;
import prerna.sablecc2.om.GenRowStruct;
import prerna.sablecc2.om.PixelDataType;
import prerna.sablecc2.om.PixelOperationType;
import prerna.sablecc2.om.ReactorKeysEnum;
import prerna.sablecc2.om.nounmeta.NounMetadata;
import prerna.util.Constants;
import prerna.util.Utility;

public class ToPPTReactor extends AbstractReactor {

	private static final Logger logger = LogManager.getLogger(ToPPTReactor.class);

	private static final String CLASS_NAME = ToPPTReactor.class.getName();

	public ToPPTReactor() {
		this.keysToGet = new String[] { ReactorKeysEnum.BASE_URL.getKey(), ReactorKeysEnum.URL.getKey(),
				ReactorKeysEnum.FILE_NAME.getKey(), ReactorKeysEnum.FILE_PATH.getKey(), ReactorKeysEnum.IMAGE_WAIT_TIME.getKey() };
	}

	@Override
	public NounMetadata execute() {
		Logger logger = getLogger(CLASS_NAME);
		organizeKeys();
		User user = this.insight.getUser();
		// throw error is user doesn't have rights to export data
		if(AbstractSecurityUtils.adminSetExporter() && !SecurityQueryUtils.userIsExporter(user)) {
			AbstractReactor.throwUserNotExporterError();
		}
		String insightFolder = this.insight.getInsightFolder();
		String baseUrl = this.keyValue.get(this.keysToGet[0]);
		Integer waitTime = null;
		String waitTimeStr = this.keyValue.get(this.keysToGet[4]);
		if(waitTimeStr != null && (waitTimeStr=waitTimeStr.trim()).isEmpty()) {
			try {
				waitTime = Integer.parseInt(waitTimeStr);
			} catch(NumberFormatException e) {
				throw new IllegalArgumentException("Invalid wait time option = '" + waitTimeStr + "'. Error is: " + e.getMessage());
			}
		}
		
		List urls = getUrls();

		String sessionId = ThreadStore.getSessionId();
		// keep list of paths to clean up and delete once the pdf is created
		List tempPaths = new ArrayList<>();
		// Process all urls
		int imageNum = 1;
		for (String url : urls) {
			// Run headless chrome with semossTagUrl
			String imagePath = insightFolder + DIR_SEPARATOR + "image" + imageNum + ".png";
			logger.info("Generating image for PPT...");
			this.insight.getChromeDriver().captureImage(baseUrl, url, imagePath, sessionId, waitTime);
			tempPaths.add(imagePath);
			logger.info("Done generating image for PPT...");
			imageNum += 1;
		}

		String downloadKey = UUID.randomUUID().toString();
		InsightFile insightFile = new InsightFile();
		insightFile.setFileKey(downloadKey);
		
		// get a random file name
		// grab file path to write the file
		String prefixName =  Utility.normalizePath(this.keyValue.get(ReactorKeysEnum.FILE_NAME.getKey()));
		String exportName = AbstractExportTxtReactor.getExportFileName(user, prefixName, "pptx");
		String fileLocation = this.keyValue.get(ReactorKeysEnum.FILE_PATH.getKey());
		// if the file location is not defined generate a random path and set
		// location so that the front end will download
		if (fileLocation == null) {
			fileLocation = insightFolder + DIR_SEPARATOR + exportName;
			insightFile.setDeleteOnInsightClose(true);
		} else {
			fileLocation += DIR_SEPARATOR + exportName;
			insightFile.setDeleteOnInsightClose(false);
		}
		insightFile.setFilePath(fileLocation);

		// Insert images into powerpoint
		XMLSlideShow slideshow = new XMLSlideShow();
		for (String path : tempPaths) {
			byte[] pic = null;
			try {
				pic = IOUtils.toByteArray(new FileInputStream(Utility.normalizePath(path)));
			} catch (FileNotFoundException e) {
				logger.error(Constants.STACKTRACE, e);
			} catch (IOException ioe) {
				logger.error(Constants.STACKTRACE, ioe);
			}
			XSLFPictureData picData = slideshow.addPicture(pic, PictureType.PNG);
			Rectangle picBounds = createStandardPowerPointImageBounds();

			XSLFSlide slide = slideshow.createSlide();
			XSLFPictureShape pictureShape = slide.createPicture(picData);
			pictureShape.setAnchor(picBounds);
		}

		// Delete temp files
		for (String path : tempPaths) {
			try {
				File f = new File(Utility.normalizePath(path));
				if (f.exists()) {
					FileUtils.forceDelete(f);
				}
			} catch (IOException e) {
				logger.error(Constants.STACKTRACE, e);
			}
		}
		writeToFile(slideshow, fileLocation);

		// store the insight file 
		// in the insight so the FE can download it
		// only from the given insight
		this.insight.addExportFile(downloadKey, insightFile);
		return new NounMetadata(downloadKey, PixelDataType.CONST_STRING, PixelOperationType.FILE_DOWNLOAD);
	}

	private List getUrls() {
		GenRowStruct colGrs = this.store.getNoun(keysToGet[1]);
		int size = colGrs.size();
		List columns = new ArrayList<>();
		for (int i = 0; i < size; i++) {
			columns.add(colGrs.get(i).toString());
		}
		return columns;
	}

	private Rectangle createStandardPowerPointImageBounds() {
		// Point DPI = 72 = 1 inch
		// Maintain 1920 x 1080 aspect ratio - let's fit to the width of the
		// slide
		double dpiPerInch = (double) Units.POINT_DPI;
		double slideWidth = 10;
		double slideHeight = 7.5;
		double widthOffsetInches = 0.1;
		double widthOffsetDPI = widthOffsetInches * dpiPerInch;
		double heightWidthAspectRatio = 1080.0 / 1920.0;

		double imageWidthDPI = ((slideWidth * dpiPerInch) - (2 * widthOffsetDPI));
		double imageHeightDPI = (imageWidthDPI * heightWidthAspectRatio);

		// Figure out height offset so that the image is in the middle of the
		// slide
		double slideHeightDPI = slideHeight * dpiPerInch;
		double heightOffsetDPI = ((slideHeightDPI - imageHeightDPI) / 2);

		// Cast coordinates to int so that they can be ingested by Rectangle
		int widthOffsetDPIInt = (int) widthOffsetDPI;
		int heightOffsetDPIInt = (int) heightOffsetDPI;
		int imageWidthDPIInt = (int) imageWidthDPI;
		int imageHeightDPIInt = (int) imageHeightDPI;

		return new java.awt.Rectangle(widthOffsetDPIInt, heightOffsetDPIInt, imageWidthDPIInt, imageHeightDPIInt);
	}

	private void writeToFile(XMLSlideShow slideshow, String path) {
		try {
			OutputStream out = new FileOutputStream(path);
			slideshow.write(out);
		} catch (FileNotFoundException e) {
			logger.error(Constants.STACKTRACE, e);
		} catch (IOException ioe) {
			logger.error(Constants.STACKTRACE, ioe);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy