Class XfdfImporter
- java.lang.Object
-
- com.pd4ml.pdf.xfdf.XfdfImporter
-
public final class XfdfImporter extends java.lang.ObjectImports an XFDF document's (ISO 19444-1) annotations and form field values into a PDF -- built entirely on the pd4mlcom.pd4ml.pdf.cosobject model/parser (no PDFBox, no other PDF library), the same foundationcom.pd4ml.pdf.sign,com.pd4ml.pdf.mergeandcom.pd4ml.pdf.optimizerare built on.Each
<annots>entry is matched to an existing PDF annotation by itsnameattribute (the PDF/NMunique identifier), independently ofXfdfImporter.Options.updateIfExists(boolean):updateIfExists(true)(defaultfalse) -- an existing match is updated in place (its position, appearance-relevant properties, and content are overwritten from the XFDF; anything the XFDF doesn't mention is left as-is). No match means a new annotation is added, exactly as with the switch off.updateIfExists(false)-- every<annots>entry becomes a new annotation, even if itsnamecollides with one already present (a plain, literal "add everything" import, matching how a viewer's basic "Import Annotations" command usually behaves).
inreplyto) is resolved against the combined set of annotations already in the PDF and everything else in this same XFDF batch, in a second pass once every annotation in the batch has been created or matched -- so it works regardless of which order the XFDF lists a thread's replies in.<fields>entries only ever update a field that already exists in the target PDF's/AcroForm(seeFieldMapper's class documentation for why, and for the signature-field exclusion); a name with no match is reported back viaXfdfImporter.Result.getFieldsNotFound()rather than silently dropped or fabricated. Since a field update only ever changes an existing widget's value in place -- never adding a new one -- it never touches the target's accessibility structure tree either way: a widget that was already tagged stays exactly as tagged as it was before.Tagged (accessibility-structured) target PDFs: a brand-new annotation added from an
<annots>entry is additionally wired into the target's existing/StructTreeRoot, if it has one, per the Matterhorn Protocol / PDF/UA-1 rules -- seeStructureTreeUpdater's class documentation for exactly how, and which annotations are (and aren't) tagged. A target with no existing/StructTreeRootis left untagged, exactly as before -- this only ever extends structure that's already there.Selecting a subset of the XFDF to actually apply -- rather than every annotation and field it contains -- is what
XfdfImporter.Options.types(String)andXfdfImporter.Options.ids(String)are for; see their own documentation for the exact matching rules. Both are optional and independent of each other, and ofXfdfImporter.Options.updateIfExists(boolean).Encrypted input is supported the same way every other pd4ml PDF feature supports it: pass the password to
XfdfImporter.Options.password(String). The imported output stays plain unlessXfdfImporter.Options.encryptOutput(java.lang.String, java.lang.String)is also given. Optimizing the output -- collapsing incremental-update history and dropping unreferenced objects, seecom.pd4ml.pdf.optimizer.PdfOptimizer-- is available viaXfdfImporter.Options.optimizeOutput(boolean); when combined withXfdfImporter.Options.encryptOutput(java.lang.String, java.lang.String), optimization always runs first and encryption is applied to its result, since encrypting first would leave the optimizer trying to reachability-walk ciphertext.Thread-safety:
XfdfImporterholds no state at all (every method isstatic); callimportInto(...)freely and concurrently from any number of threads.Example
XfdfImporter.Options options = new XfdfImporter.Options() .updateIfExists(true) .optimizeOutput(true) .encryptOutput("open123", "owner456"); XfdfImporter.Result result = XfdfImporter.importInto(pdfBytes, xfdfBytes, options); Files.write(Paths.get("annotated.pdf"), result.getPdf());
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classXfdfImporter.Optionsstatic classXfdfImporter.ResultThe imported PDF, plus bookkeeping on what the import actually did.
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static XfdfImporter.ResultimportInto(byte[] pdfBytes, byte[] xfdfBytes)static XfdfImporter.ResultimportInto(byte[] pdfBytes, byte[] xfdfBytes, XfdfImporter.Options options)static XfdfImporter.ResultimportInto(byte[] pdfBytes, byte[] xfdfBytes, XfdfImporter.Options options, java.io.OutputStream out)Convenience for writing the imported PDF straight to a destination rather than handlingXfdfImporter.Resultyourself.static XfdfImporter.ResultimportInto(java.io.File pdfFile, java.io.File xfdfFile)static XfdfImporter.ResultimportInto(java.io.File pdfFile, java.io.File xfdfFile, XfdfImporter.Options options)static XfdfImporter.ResultimportInto(java.io.File pdfFile, java.io.File xfdfFile, XfdfImporter.Options options, java.io.File outputFile)static XfdfImporter.ResultimportInto(java.io.InputStream pdfIn, java.io.InputStream xfdfIn, XfdfImporter.Options options)
-
-
-
Method Detail
-
importInto
public static XfdfImporter.Result importInto(byte[] pdfBytes, byte[] xfdfBytes) throws XfdfException
- Throws:
XfdfException
-
importInto
public static XfdfImporter.Result importInto(byte[] pdfBytes, byte[] xfdfBytes, XfdfImporter.Options options) throws XfdfException
- Throws:
XfdfException
-
importInto
public static XfdfImporter.Result importInto(java.io.File pdfFile, java.io.File xfdfFile) throws XfdfException
- Throws:
XfdfException
-
importInto
public static XfdfImporter.Result importInto(java.io.File pdfFile, java.io.File xfdfFile, XfdfImporter.Options options) throws XfdfException
- Throws:
XfdfException
-
importInto
public static XfdfImporter.Result importInto(java.io.InputStream pdfIn, java.io.InputStream xfdfIn, XfdfImporter.Options options) throws XfdfException
- Throws:
XfdfException
-
importInto
public static XfdfImporter.Result importInto(byte[] pdfBytes, byte[] xfdfBytes, XfdfImporter.Options options, java.io.OutputStream out) throws XfdfException
Convenience for writing the imported PDF straight to a destination rather than handlingXfdfImporter.Resultyourself.- Throws:
XfdfException
-
importInto
public static XfdfImporter.Result importInto(java.io.File pdfFile, java.io.File xfdfFile, XfdfImporter.Options options, java.io.File outputFile) throws XfdfException
- Throws:
XfdfException
-
-