com.adobe.pdfservices.operation.pdfops.SplitPDFOperation Maven / Gradle / Ivy
Show all versions of pdfservices-sdk Show documentation
/*
* Copyright 2019 Adobe
* All Rights Reserved.
*
* NOTICE: Adobe permits you to use, modify, and distribute this file in
* accordance with the terms of the Adobe license agreement accompanying
* it. If you have received this file from a source other than Adobe,
* then your use, modification, or distribution of it requires the prior
* written permission of Adobe.
*/
package com.adobe.pdfservices.operation.pdfops;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import com.adobe.pdfservices.operation.exception.ServiceApiException;
import com.adobe.pdfservices.operation.exception.ServiceUsageException;
import com.adobe.pdfservices.operation.internal.ExtensionMediaTypeMapping;
import com.adobe.pdfservices.operation.internal.FileRefImpl;
import com.adobe.pdfservices.operation.internal.InternalExecutionContext;
import com.adobe.pdfservices.operation.internal.MediaType;
import com.adobe.pdfservices.operation.internal.api.FileDownloadApi;
import com.adobe.pdfservices.operation.internal.cpf.dto.response.platform.CPFContentAnalyzerResponse;
import com.adobe.pdfservices.operation.internal.exception.OperationException;
import com.adobe.pdfservices.operation.internal.service.SplitPDFService;
import com.adobe.pdfservices.operation.internal.util.StringUtil;
import com.adobe.pdfservices.operation.internal.util.ValidationUtil;
import com.adobe.pdfservices.operation.ExecutionContext;
import com.adobe.pdfservices.operation.Operation;
import com.adobe.pdfservices.operation.io.FileRef;
import com.adobe.pdfservices.operation.pdfops.options.PageRanges;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An operation that splits PDF document into multiple smaller documents by simply specifying either the number of files,
* pages per file, or page ranges.
*
*
* Sample Usage:
*
{@code SplitPDFOperation splitPDFOperation = SplitPDFOperation.createNew();
* splitPDFOperation.setInput(FileRef.createFromLocalFile("~/Documents/splitPDFOperationInput.pdf",
* SplitPDFOperation.SupportedSourceFormat.PDF.getMediaType()));
* splitPDFOperation.setPageCount(2);
* Credentials credentials = Credentials.serviceAccountCredentialsBuilder().fromFile("pdfservices-api-credentials.json").build();
* List result = splitPDFOperation.execute(ExecutionContext.create(credentials));
* int index = 0;
* for (FileRef fileRef : result) {
* fileRef.saveAs("output/splitPDFOperationOutput_" + index + ".pdf");
* index++;
* }
* }
*/
public class SplitPDFOperation implements Operation {
private static final Logger LOGGER = LoggerFactory.getLogger(SplitPDFOperation.class);
/**
* Supported media types for this operation
*/
private static final Set SUPPORTED_SOURCE_MEDIA_TYPES =
new HashSet<>(Collections.singletonList(ExtensionMediaTypeMapping.PDF.getMediaType()));
/**
* Field representing the extension of the operation result
*/
private static final String TARGET_FILE_EXTENSION = ExtensionMediaTypeMapping.PDF.getExtension();
/**
* Variable to check if the operation instance was invoked more than once
*/
private boolean isInvoked = false;
private FileRefImpl sourceFileRef;
private PageRanges pageRanges;
private Integer pageCount;
private Integer fileCount;
private SplitPDFOperation() {
}
/**
* Constructs a {@code SplitPDFOperation} instance.
*
* @return a new {@code SplitPDFOperation} instance
*/
public static SplitPDFOperation createNew() {
return new SplitPDFOperation();
}
/**
* Sets an input file.
*
* @param sourceFileRef an input file; can not be null
*/
public void setInput(FileRef sourceFileRef) {
Objects.requireNonNull(sourceFileRef, "No input was set for operation");
this.sourceFileRef = (FileRefImpl) sourceFileRef;
}
/**
* Sets the page ranges on the basis of which to split the input PDF file.
* Each page range corresponds to a single output file having the pages specified in the page range.
*
* @param pageRanges page ranges for split; can not be null or empty
*/
public void setPageRanges(PageRanges pageRanges) {
this.pageRanges = pageRanges;
}
/**
* Sets the maximum number of pages each of the output files can have.
*
* @param pageCount maximum number of pages per output file
*/
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
/**
* Sets the number of documents to split the input PDF.
*
* @param fileCount represents the number of output files
*/
public void setFileCount(int fileCount) {
this.fileCount = fileCount;
}
/**
* Executes this operation synchronously using the supplied context and returns a new list of FileRef instances for the resultant PDF files.
*
* The resultant files may be stored in the system temporary directory (per java.io.tmpdir System property).
* See {@link FileRef} for how temporary resources are cleaned up.
*
* @param context the context in which to execute the operation
* @return list of resultant PDF files
* @throws ServiceApiException if an API call results in an error response
* @throws IOException if there is an error in reading either the input source or the resulting PDF file
* @throws ServiceUsageException if service usage limits have been reached or credentials quota has been exhausted
*/
public List execute(ExecutionContext context) throws ServiceApiException, IOException, ServiceUsageException {
validateInvocationCount();
InternalExecutionContext internalExecutionContext = (InternalExecutionContext) context;
this.validate(internalExecutionContext);
try {
LOGGER.info("All validations successfully done. Beginning Split PDF operation execution");
long startTimeMs = System.currentTimeMillis();
String location = SplitPDFService.splitPDF(internalExecutionContext,
sourceFileRef, pageRanges, pageCount, fileCount, this.getClass().getSimpleName());
List temporaryDestinationPaths = FileDownloadApi.downloadAndSaveMultiple(internalExecutionContext,
location, TARGET_FILE_EXTENSION, CPFContentAnalyzerResponse.class);
LOGGER.info("Operation successfully completed. Stored requisite PDF at {}", temporaryDestinationPaths.toString());
LOGGER.debug("Operation Success Info - Request ID: {}, Latency(ms): {}",
StringUtil.getRequestIdFromLocation(location), System.currentTimeMillis() - startTimeMs);
isInvoked = true;
List fileRefList = new ArrayList<>();
for(String path : temporaryDestinationPaths) {
fileRefList.add(FileRef.createFromLocalFile(path));
}
return fileRefList;
} catch (OperationException oe) {
throw new ServiceApiException(oe.getErrorMessage(), oe.getRequestTrackingId(), oe.getStatusCode(), oe.getReportErrorCode());
}
}
private void validateInvocationCount() {
if (isInvoked) {
LOGGER.error("Operation instance must only be invoked once");
throw new IllegalStateException("Operation instance must not be reused, can only be invoked once");
}
}
private void validate(InternalExecutionContext context) {
if (sourceFileRef == null) {
throw new IllegalArgumentException("No input was set for operation");
}
ValidationUtil.validateSplitPDFOperationParams(pageRanges, pageCount, fileCount);
ValidationUtil.validateExecutionContext(context);
ValidationUtil.validateMediaType(SUPPORTED_SOURCE_MEDIA_TYPES, this.sourceFileRef.getMediaType());
}
/**
* Supported source file formats for {@link SplitPDFOperation}.
*/
public enum SupportedSourceFormat implements MediaType {
/**
* Represents "application/pdf" media type
*/
PDF;
/**
* Returns the corresponding media type for this format, intended to be used for {@code mediaType} parameter in
* {@link FileRef} methods.
*
* @return the corresponding media type
*/
public String getMediaType() {
return ExtensionMediaTypeMapping.valueOf(name()).getMediaType().toLowerCase();
}
}
}