com.pdftools.pdfa.conversion.Converter Maven / Gradle / Ivy
Show all versions of pdftools-sdk Show documentation
/****************************************************************************
*
* File: Converter.java
*
* Description: PDFTOOLS Converter Class
*
* Author: PDF Tools AG
*
* Copyright: Copyright (C) 2023 - 2024 PDF Tools AG, Switzerland
* All rights reserved.
*
* Notice: By downloading and using this artifact, you accept PDF Tools AG's
* [license agreement](https://www.pdf-tools.com/license-agreement/),
* [privacy policy](https://www.pdf-tools.com/privacy-policy/),
* and allow PDF Tools AG to track your usage data.
*
***************************************************************************/
package com.pdftools.pdfa.conversion;
import com.pdftools.sys.*;
import com.pdftools.internal.*;
import java.util.EnumSet;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.*;
/**
* The class to convert PDF documents to PDF/A
*/
public class Converter extends NativeObject
{
protected Converter(long handle)
{
super(handle);
}
/**
* @hidden
*/
public static Converter createDynamicObject(long handle)
{
return new Converter(handle);
}
/***
* Listener interface for the {@link ConversionEvent} event.
*
*/
public interface ConversionEventListener extends EventListener
{
void conversionEvent(ConversionEvent event);
}
/**
* The event for errors, warnings, and informational messages that occur during conversion
*
* Report a conversion event that occurred in {@link Converter#convert }.
* These events can be used to:
*
* -
* Generate a detailed conversion report.
* -
* Detect and handle critical conversion events.
*
*
* Note that if a document cannot be converted to the requested conformance, the {@link Converter#convert } throws an exception.
* However, even if the output document meets all required standards, the conversion might have resulted in differences that might be acceptable in some processes but not in others.
* Such potentially critical conversion issues are reported as conversion events.
*
* We suggest checking which conversion events can be tolerated in your conversion process and which must be considered critical:
*
* -
* Review the suggested severity of events.
* Each event has a default severity indicated by {@code severity} which is based on the event's {@code category}.
* Review the suggested severity of each {@link EventCategory } and determine the {@link EventSeverity } to be used in your process.
*
* -
* Handle events according to their severity.
*
* -
* Events of severity {@link EventSeverity#ERROR }:
* The conversion must be considered as failed.
*
* -
*
* Events of severity {@link EventSeverity#WARNING }:
* In case of a warning, the output file is best presented to a user to decide if the result is acceptable.
* The properties {@code message}, {@code context}, and {@code page} in combination with the output file are helpful to make this decision.
*
* If a manual review is not feasible, critical warnings should be classified as an {@link EventSeverity#ERROR }.
* An exception to this is, if all processed input documents are similar in their content, e.g. because they have been created by a single source (application).
* In this case, the conversion result can be verified using representative test files and the event severity chosen accordingly.
*
* -
* Events of severity {@link EventSeverity#INFORMATION }:
* No further action is required.
*
*
*
*/
public class ConversionEvent extends EventObject
{
private static final long serialVersionUID = 1576L;
private String dataPart;
private String message;
private com.pdftools.pdfa.conversion.EventSeverity severity;
private com.pdftools.pdfa.conversion.EventCategory category;
private com.pdftools.pdfa.conversion.EventCode code;
private String context;
private int pageNo;
private ConversionEvent(Object source, String dataPart, String message, com.pdftools.pdfa.conversion.EventSeverity severity, com.pdftools.pdfa.conversion.EventCategory category, com.pdftools.pdfa.conversion.EventCode code, String context, int pageNo) {
super(source);
this.dataPart = dataPart;
this.message = message;
this.severity = severity;
this.category = category;
this.code = code;
this.context = context;
this.pageNo = pageNo;
}
/**
*
* The data part is {@code null} for the main file and a data part specification for embedded files.
*
* Examples:
*
* -
* {@code embedded-file:file.pdf}: For a file {@code file.pdf} that is embedded in the main file.
* -
* {@code embedded-file:file1.pdf/embedded-file:file2.pdf}: For a file {@code file2.pdf} that is embedded in an embedded file {@code file1.pdf}.
*
*/
public String getDataPart() {
return dataPart;
}
/**
* The event message
*/
public String getMessage() {
return message;
}
/**
*
* The suggested severity of the event.
*
* We suggest checking, which conversion events are tolerable in your conversion process and which must be considered critical.
* See the documentation of {@link Converter.ConversionEventListener } for a more detailed description.
*
*/
public com.pdftools.pdfa.conversion.EventSeverity getSeverity() {
return severity;
}
/**
* The category of the event. This parameter can be used to:
*
* -
* Classify the severity of an event
* -
* Specialized handling of events
*
* See the documentation of {@link Converter.ConversionEventListener } for a more detailed description.
*/
public com.pdftools.pdfa.conversion.EventCategory getCategory() {
return category;
}
/**
* The code identifying particular events which can be used for detection and specialized handling of specific events.
* For most applications, it suffices to handle events by {@code category}.
*/
public com.pdftools.pdfa.conversion.EventCode getCode() {
return code;
}
/**
* A description of the context where the event occurred
*/
public String getContext() {
return context;
}
/**
* The page this event is associated to or {@code 0}
*/
public int getPageNo() {
return pageNo;
}
}
private Hashtable conversionEventDic = new Hashtable();
private class ConversionEventNativeClass
{
private ConversionEventListener listener;
private long context;
public ConversionEventNativeClass(ConversionEventListener listener)
{
this.listener = listener;
}
public void conversionEventHandler(String dataPart, String message, com.pdftools.pdfa.conversion.EventSeverity severity, com.pdftools.pdfa.conversion.EventCategory category, com.pdftools.pdfa.conversion.EventCode code, String context, int pageNo)
{
ConversionEvent event = new ConversionEvent(this, dataPart, message, severity, category, code, context, pageNo);
try {
this.listener.conversionEvent(event);
}
catch (Exception ex) { }
}
}
/**
* Add a listener for the {@link ConversionEvent} event.
* @param listener Listener for the {@link ConversionEvent} event.
* If a listener is added that is already registered, it is ignored.
*/
public void addConversionEventListener(ConversionEventListener listener)
{
if(!conversionEventDic.containsKey(listener))
{
ConversionEventNativeClass eventNativeClass = new ConversionEventNativeClass(listener);
long context = addConversionEventHandlerNative(getHandle(), eventNativeClass);
if (context == 0)
throwLastRuntimeException();
eventNativeClass.context = context;
conversionEventDic.put(listener, eventNativeClass);
}
}
/**
* Remove registered listener for the {@link ConversionEvent} event.
* @param listener Listener for the {@link ConversionEvent} event that should be removed.
* If the listener is not registered, it is ignored.
*/
public void removeConversionEventListener(ConversionEventListener listener)
{
if(conversionEventDic.containsKey(listener))
{
if (!removeConversionEventHandlerNative(getHandle(), conversionEventDic.get(listener).context))
{
if (getLastErrorCode() != 5)
throwLastRuntimeException();
}
conversionEventDic.remove(listener);
}
}
/**
*
*/
public Converter()
{
this(newHelper());
}
private static long newHelper()
{
long handle = newNative();
if (handle == 0)
{
switch (getLastErrorCode())
{
case 0: throw new RuntimeException("An unexpected error occurred");
default: throwLastRuntimeException();
}
}
return handle;
}
/**
* Prepares the invoice XML file (ZUGFeRD or Factur-X) for embedding.
* Note: This requires the compliance to be set to PDF/A-3.
* @param invoiceType
* The type of invoice.
* @param invoice
* The XML invoice stream.
*
* @throws IllegalArgumentException The invoice stream could not be opened for reading.
* @throws IllegalArgumentException if {@code invoiceType} is {@code null}
* @throws IllegalArgumentException if {@code invoice} is {@code null}
*/
public void addInvoiceXml(com.pdftools.pdfa.conversion.InvoiceType invoiceType, com.pdftools.sys.Stream invoice)
{
if (invoiceType == null)
throw new IllegalArgumentException("Argument 'invoiceType' must not be null.", new NullPointerException("'invoiceType'"));
if (invoice == null)
throw new IllegalArgumentException("Argument 'invoice' must not be null.", new NullPointerException("'invoice'"));
addInvoiceXml(invoiceType, invoice, null);
}
/**
* Prepares the invoice XML file (ZUGFeRD or Factur-X) for embedding.
* Note: This requires the compliance to be set to PDF/A-3.
* @param invoiceType
* The type of invoice.
* @param invoice
* The XML invoice stream.
* @param afRelationship
* If no value is provided, a sensible default value is chosen based on the invoice type and version.
*
* @throws IllegalArgumentException The invoice stream could not be opened for reading.
* @throws IllegalArgumentException if {@code invoiceType} is {@code null}
* @throws IllegalArgumentException if {@code invoice} is {@code null}
*/
public void addInvoiceXml(com.pdftools.pdfa.conversion.InvoiceType invoiceType, com.pdftools.sys.Stream invoice, com.pdftools.pdfa.conversion.AFRelationship afRelationship)
{
if (invoiceType == null)
throw new IllegalArgumentException("Argument 'invoiceType' must not be null.", new NullPointerException("'invoiceType'"));
if (invoice == null)
throw new IllegalArgumentException("Argument 'invoice' must not be null.", new NullPointerException("'invoice'"));
boolean retVal = addInvoiceXmlNative(getHandle(), invoiceType.getValue(), invoice, afRelationship == null ? 0 : afRelationship.getValue(), afRelationship == null);
if (!retVal)
{
switch (getLastErrorCode())
{
case 0: throw new RuntimeException("An unexpected error occurred");
case 3: throw new IllegalArgumentException(getLastErrorMessage());
default: throwLastRuntimeException();
}
}
}
/**
* Convert a document to PDF/A.
* Note that it is highly recommended to use {@link Converter.ConversionEventListener } to detect critical conversion events.
* @param analysis
* The result of the document's analysis using {@link com.pdftools.pdfa.validation.Validator#analyze pdftools.pdfa.validation.Validator.analyze}.
* @param document
* The document to convert
* @param outStream
* The stream where the converted document is written
* @return
* The result of the conversion
*
* @throws com.pdftools.LicenseException The license check has failed.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert outOptions} argument is invalid.
* @throws IllegalArgumentException The output stream could not be opened for writing.
* @throws IllegalStateException The {@link com.pdftools.pdfa.conversion.Converter#convert document} has already been closed.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert analysis} has already been closed, e.g. due to a previous conversion.
* @throws IllegalArgumentException The PDF/A version of the analysis and the conversion options do not match.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert analysis} is not the analysis result of {@link com.pdftools.pdfa.conversion.Converter#convert document}.
* @throws java.io.IOException Error reading from or writing to the {@link com.pdftools.pdfa.conversion.Converter#convert outStream}.
* @throws com.pdftools.ConformanceException The conformance required by {@link com.pdftools.pdfa.conversion.Converter#convert options} cannot be achieved.
*
* -
* PDF/A level U: All text of the input document must be extractable.
* -
* PDF/A level A: In addition to the requirements of level U, the input document must be tagged.
*
* @throws com.pdftools.ConformanceException The PDF/A version of the conformances of {@link com.pdftools.pdfa.conversion.Converter#convert analysis} and {@link com.pdftools.pdfa.conversion.Converter#convert options} differ.
* The same PDF/A version must be used for the analysis and conversion.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert outOptions} specifies document encryption, which is not allowed in PDF/A documents.
* @throws com.pdftools.GenericException The document cannot be converted to PDF/A.
* @throws com.pdftools.CorruptException The analysis has been stopped.
* @throws com.pdftools.ProcessingException Failed to add the invoice file.
* Possible reasons include an invalid XML format, or that the invoice type conflicts with the content of the XML file.
* @throws com.pdftools.UnsupportedFeatureException The document is not a PDF, but an XFA document.
* See {@link com.pdftools.pdf.Document#getXfa pdftools.pdf.Document.getXfa} for more information on how to detect and handle XFA documents.
* @throws com.pdftools.NotFoundException A required font is missing from the installed font directories.
* @throws IllegalArgumentException if {@code analysis} is {@code null}
* @throws IllegalArgumentException if {@code document} is {@code null}
* @throws IllegalArgumentException if {@code outStream} is {@code null}
*/
public com.pdftools.pdf.Document convert(com.pdftools.pdfa.validation.AnalysisResult analysis, com.pdftools.pdf.Document document, com.pdftools.sys.Stream outStream)
throws
java.io.IOException,
com.pdftools.NotFoundException,
com.pdftools.GenericException,
com.pdftools.LicenseException,
com.pdftools.CorruptException,
com.pdftools.ConformanceException,
com.pdftools.UnsupportedFeatureException,
com.pdftools.ProcessingException
{
if (analysis == null)
throw new IllegalArgumentException("Argument 'analysis' must not be null.", new NullPointerException("'analysis'"));
if (document == null)
throw new IllegalArgumentException("Argument 'document' must not be null.", new NullPointerException("'document'"));
if (outStream == null)
throw new IllegalArgumentException("Argument 'outStream' must not be null.", new NullPointerException("'outStream'"));
return convert(analysis, document, outStream, null, null);
}
/**
* Convert a document to PDF/A.
* Note that it is highly recommended to use {@link Converter.ConversionEventListener } to detect critical conversion events.
* @param analysis
* The result of the document's analysis using {@link com.pdftools.pdfa.validation.Validator#analyze pdftools.pdfa.validation.Validator.analyze}.
* @param document
* The document to convert
* @param outStream
* The stream where the converted document is written
* @param options
* The conversion options
* @return
* The result of the conversion
*
* @throws com.pdftools.LicenseException The license check has failed.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert outOptions} argument is invalid.
* @throws IllegalArgumentException The output stream could not be opened for writing.
* @throws IllegalStateException The {@link com.pdftools.pdfa.conversion.Converter#convert document} has already been closed.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert analysis} has already been closed, e.g. due to a previous conversion.
* @throws IllegalArgumentException The PDF/A version of the analysis and the conversion options do not match.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert analysis} is not the analysis result of {@link com.pdftools.pdfa.conversion.Converter#convert document}.
* @throws java.io.IOException Error reading from or writing to the {@link com.pdftools.pdfa.conversion.Converter#convert outStream}.
* @throws com.pdftools.ConformanceException The conformance required by {@link com.pdftools.pdfa.conversion.Converter#convert options} cannot be achieved.
*
* -
* PDF/A level U: All text of the input document must be extractable.
* -
* PDF/A level A: In addition to the requirements of level U, the input document must be tagged.
*
* @throws com.pdftools.ConformanceException The PDF/A version of the conformances of {@link com.pdftools.pdfa.conversion.Converter#convert analysis} and {@link com.pdftools.pdfa.conversion.Converter#convert options} differ.
* The same PDF/A version must be used for the analysis and conversion.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert outOptions} specifies document encryption, which is not allowed in PDF/A documents.
* @throws com.pdftools.GenericException The document cannot be converted to PDF/A.
* @throws com.pdftools.CorruptException The analysis has been stopped.
* @throws com.pdftools.ProcessingException Failed to add the invoice file.
* Possible reasons include an invalid XML format, or that the invoice type conflicts with the content of the XML file.
* @throws com.pdftools.UnsupportedFeatureException The document is not a PDF, but an XFA document.
* See {@link com.pdftools.pdf.Document#getXfa pdftools.pdf.Document.getXfa} for more information on how to detect and handle XFA documents.
* @throws com.pdftools.NotFoundException A required font is missing from the installed font directories.
* @throws IllegalArgumentException if {@code analysis} is {@code null}
* @throws IllegalArgumentException if {@code document} is {@code null}
* @throws IllegalArgumentException if {@code outStream} is {@code null}
*/
public com.pdftools.pdf.Document convert(com.pdftools.pdfa.validation.AnalysisResult analysis, com.pdftools.pdf.Document document, com.pdftools.sys.Stream outStream, com.pdftools.pdfa.conversion.ConversionOptions options)
throws
java.io.IOException,
com.pdftools.NotFoundException,
com.pdftools.GenericException,
com.pdftools.LicenseException,
com.pdftools.CorruptException,
com.pdftools.ConformanceException,
com.pdftools.UnsupportedFeatureException,
com.pdftools.ProcessingException
{
if (analysis == null)
throw new IllegalArgumentException("Argument 'analysis' must not be null.", new NullPointerException("'analysis'"));
if (document == null)
throw new IllegalArgumentException("Argument 'document' must not be null.", new NullPointerException("'document'"));
if (outStream == null)
throw new IllegalArgumentException("Argument 'outStream' must not be null.", new NullPointerException("'outStream'"));
return convert(analysis, document, outStream, options, null);
}
/**
* Convert a document to PDF/A.
* Note that it is highly recommended to use {@link Converter.ConversionEventListener } to detect critical conversion events.
* @param analysis
* The result of the document's analysis using {@link com.pdftools.pdfa.validation.Validator#analyze pdftools.pdfa.validation.Validator.analyze}.
* @param document
* The document to convert
* @param outStream
* The stream where the converted document is written
* @param options
* The conversion options
* @param outOptions
* The output options object
* @return
* The result of the conversion
*
* @throws com.pdftools.LicenseException The license check has failed.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert outOptions} argument is invalid.
* @throws IllegalArgumentException The output stream could not be opened for writing.
* @throws IllegalStateException The {@link com.pdftools.pdfa.conversion.Converter#convert document} has already been closed.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert analysis} has already been closed, e.g. due to a previous conversion.
* @throws IllegalArgumentException The PDF/A version of the analysis and the conversion options do not match.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert analysis} is not the analysis result of {@link com.pdftools.pdfa.conversion.Converter#convert document}.
* @throws java.io.IOException Error reading from or writing to the {@link com.pdftools.pdfa.conversion.Converter#convert outStream}.
* @throws com.pdftools.ConformanceException The conformance required by {@link com.pdftools.pdfa.conversion.Converter#convert options} cannot be achieved.
*
* -
* PDF/A level U: All text of the input document must be extractable.
* -
* PDF/A level A: In addition to the requirements of level U, the input document must be tagged.
*
* @throws com.pdftools.ConformanceException The PDF/A version of the conformances of {@link com.pdftools.pdfa.conversion.Converter#convert analysis} and {@link com.pdftools.pdfa.conversion.Converter#convert options} differ.
* The same PDF/A version must be used for the analysis and conversion.
* @throws IllegalArgumentException The {@link com.pdftools.pdfa.conversion.Converter#convert outOptions} specifies document encryption, which is not allowed in PDF/A documents.
* @throws com.pdftools.GenericException The document cannot be converted to PDF/A.
* @throws com.pdftools.CorruptException The analysis has been stopped.
* @throws com.pdftools.ProcessingException Failed to add the invoice file.
* Possible reasons include an invalid XML format, or that the invoice type conflicts with the content of the XML file.
* @throws com.pdftools.UnsupportedFeatureException The document is not a PDF, but an XFA document.
* See {@link com.pdftools.pdf.Document#getXfa pdftools.pdf.Document.getXfa} for more information on how to detect and handle XFA documents.
* @throws com.pdftools.NotFoundException A required font is missing from the installed font directories.
* @throws IllegalArgumentException if {@code analysis} is {@code null}
* @throws IllegalArgumentException if {@code document} is {@code null}
* @throws IllegalArgumentException if {@code outStream} is {@code null}
*/
public com.pdftools.pdf.Document convert(com.pdftools.pdfa.validation.AnalysisResult analysis, com.pdftools.pdf.Document document, com.pdftools.sys.Stream outStream, com.pdftools.pdfa.conversion.ConversionOptions options, com.pdftools.pdf.OutputOptions outOptions)
throws
java.io.IOException,
com.pdftools.NotFoundException,
com.pdftools.GenericException,
com.pdftools.LicenseException,
com.pdftools.CorruptException,
com.pdftools.ConformanceException,
com.pdftools.UnsupportedFeatureException,
com.pdftools.ProcessingException
{
if (analysis == null)
throw new IllegalArgumentException("Argument 'analysis' must not be null.", new NullPointerException("'analysis'"));
if (document == null)
throw new IllegalArgumentException("Argument 'document' must not be null.", new NullPointerException("'document'"));
if (outStream == null)
throw new IllegalArgumentException("Argument 'outStream' must not be null.", new NullPointerException("'outStream'"));
long retHandle = convertNative(getHandle(), getHandle(analysis), analysis, getHandle(document), document, outStream, getHandle(options), options, getHandle(outOptions), outOptions);
if (retHandle == 0)
{
switch (getLastErrorCode())
{
case 0: throw new RuntimeException("An unexpected error occurred");
case 2: throw new IllegalStateException(getLastErrorMessage());
case 3: throw new IllegalArgumentException(getLastErrorMessage());
case 4: throw new java.io.IOException(getLastErrorMessage());
case 5: throw new com.pdftools.NotFoundException(getLastErrorMessage());
case 10: throw new com.pdftools.GenericException(getLastErrorMessage());
case 12: throw new com.pdftools.LicenseException(getLastErrorMessage());
case 16: throw new com.pdftools.CorruptException(getLastErrorMessage());
case 18: throw new com.pdftools.ConformanceException(getLastErrorMessage());
case 19: throw new com.pdftools.UnsupportedFeatureException(getLastErrorMessage());
case 21: throw new com.pdftools.ProcessingException(getLastErrorMessage());
default: throwLastRuntimeException();
}
}
return com.pdftools.pdf.Document.createDynamicObject(retHandle);
}
private native long addConversionEventHandlerNative(long handle, ConversionEventNativeClass eventClass);
private native boolean removeConversionEventHandlerNative(long handle, long context);
private static native long newNative();
private native boolean addInvoiceXmlNative(long handle, int invoiceType, com.pdftools.sys.Stream invoice, int afRelationship, boolean isNullafRelationship);
private native long convertNative(long handle, long analysis, com.pdftools.pdfa.validation.AnalysisResult analysisObj, long document, com.pdftools.pdf.Document documentObj, com.pdftools.sys.Stream outStream, long options, com.pdftools.pdfa.conversion.ConversionOptions optionsObj, long outOptions, com.pdftools.pdf.OutputOptions outOptionsObj);
}