Class StructureTreeUpdater
- java.lang.Object
-
- com.pd4ml.pdf.xfdf.internal.StructureTreeUpdater
-
public final class StructureTreeUpdater extends java.lang.ObjectWires a brand-new PDF annotation -- oneXfdfImporterjust added from an<annots>entry, not one it merely updated in place -- into an already-tagged target document's accessibility structure tree (/StructTreeRoot), so the imported annotation doesn't silently fall outside it.Per the Matterhorn Protocol (the PDF/UA-1 test suite -- checkpoint 13), every visible annotation other than
Popupneeds a structure element referencing it via anOBJR; aLinkannotation specifically needs the standardLinkstructure type, everything else uses the genericAnnottype (a real standard structure type as of PDF 2.0/ISO 32000-2; on an older-version document aRoleMapfallback to the PDF 1.7 standard typeNoteis added alongside it so a reader that only knows the older type set still resolves it to something sensible).Popup, and any annotation flaggedHiddenorNoView(ISO 32000-1 Table 165 -- it's never rendered either way), are intentionally left untagged, matching the same exemptions.Scope: this class only ever extends a structure tree that already exists (see
forDocument(COSDocument)) -- it never adds/StructTreeRootto a PDF that didn't have one, since building a whole tag hierarchy from scratch for a document that was never tagged is a much larger, different problem than keeping an existing one consistent. A new element is appended directly under/StructTreeRoot/K(rather than nested under whichever existing top-level element happens to "belong" to the same page) -- simple and always structurally valid, at the cost of the newly-tagged annotation reading last in the document's overall structure order regardless of which page it's actually on.Thread-safety: an instance is stateful (it accumulates the parent tree/
RoleMapbookkeeping for one import batch across possibly severaltagNewAnnotation(com.pd4ml.pdf.cos.COSDictionary, com.pd4ml.pdf.cos.COSDictionary)calls beforefinish()) and mutates the oneCOSDocumentit was built for -- confine each instance to a single thread and a singleXfdfImporter.importInto(...)call, exactly howXfdfImporteritself already uses it (one fresh instance per call, viaforDocument(COSDocument), never shared or retained afterwards). Distinct instances over distinct target documents -- e.g. concurrentimportInto(...)calls on different threads -- don't interact at all: nothing here is static or shared across instances.
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description voidfinish()Finalizes bookkeeping once every annotation in this import batch has been processed: closes off a/Kids-based leaf's/Limits, and restates/StructTreeRoot/ParentTreeNextKey.static StructureTreeUpdaterforDocument(COSDocument document)Returns a new updater fordocument, ornullif it isn't tagged (no/StructTreeRoot) -- the caller's cue to skip structure-tree work for this import entirely, exactly as if this class didn't exist.voidtagNewAnnotation(COSDictionary page, COSDictionary annotDict)TagsannotDict(already attached topage's/Annots) if it's the kind of annotation that should be, per this class's own documentation.
-
-
-
Method Detail
-
forDocument
public static StructureTreeUpdater forDocument(COSDocument document)
Returns a new updater fordocument, ornullif it isn't tagged (no/StructTreeRoot) -- the caller's cue to skip structure-tree work for this import entirely, exactly as if this class didn't exist.
-
tagNewAnnotation
public void tagNewAnnotation(COSDictionary page, COSDictionary annotDict)
TagsannotDict(already attached topage's/Annots) if it's the kind of annotation that should be, per this class's own documentation. A no-op forPopupand for any annotation that never actually renders (Hidden/NoView).
-
finish
public void finish()
Finalizes bookkeeping once every annotation in this import batch has been processed: closes off a/Kids-based leaf's/Limits, and restates/StructTreeRoot/ParentTreeNextKey. A no-op, touching nothing at all, if this batch never actually tagged anything (e.g. an import that only updated<fields>values, or whose every<annots>entry matched and updated an existing annotation) -- minimal footprint on a document this class otherwise had no reason to touch.
-
-