You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2026/10/07 14:20:40 UTC

svn commit: r1938856 - in pdfbox/branches/3.0/pdfbox/src: main/java/org/apache/pdfbox/multipdf main/java/org/apache/pdfbox/pdmodel/common test/java/org/apache/pdfbox/multipdf

Author: tilman
Date: Wed Oct  7 14:20:40 2026
New Revision: 1938856

Log:
PDFBOX-6274: introduce a PDNameTreeNode.getIDTreeAsMap() method

Modified:
   pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java
   pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/Splitter.java
   pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/PDNameTreeNode.java
   pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java

Modified: pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java
==============================================================================
--- pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java	Wed Oct  7 14:17:00 2026	(r1938855)
+++ pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java	Wed Oct  7 14:20:40 2026	(r1938856)
@@ -1105,8 +1105,8 @@ public class PDFMergerUtility
         {
             destIDTree = new PDStructureElementNameTreeNode();
         }
-        Map<String, PDStructureElement> srcNames = getIDTreeAsMap(srcIDTree);
-        Map<String, PDStructureElement> destNames = getIDTreeAsMap(destIDTree);
+        Map<String, PDStructureElement> srcNames = srcIDTree.getTreeAsMap();
+        Map<String, PDStructureElement> destNames = destIDTree.getTreeAsMap();
         for (Map.Entry<String, PDStructureElement> entry : srcNames.entrySet())
         {
             if (destNames.containsKey(entry.getKey()))
@@ -1132,36 +1132,6 @@ public class PDFMergerUtility
         // stores the map into a B+Tree, see https://en.wikipedia.org/wiki/B+_tree
     }
 
-    // PDNameTreeNode.getNames() only brings one level, this is why we need this
-    // might be made public at a later time, or integrated into PDNameTreeNode with template.
-    static Map<String, PDStructureElement> getIDTreeAsMap(PDNameTreeNode<PDStructureElement> idTree)
-            throws IOException
-    {
-        if (idTree == null)
-        {
-            return new LinkedHashMap<>();
-        }
-        Map<String, PDStructureElement> names = idTree.getNames();
-        if (names == null)
-        {
-            names = new LinkedHashMap<>();
-        }
-        else
-        {
-            // must copy because the map is read only
-            names = new LinkedHashMap<>(names);
-        }
-        List<PDNameTreeNode<PDStructureElement>> kids = idTree.getKids();
-        if (kids != null)
-        {
-            for (PDNameTreeNode<PDStructureElement> kid : kids)
-            {
-                names.putAll(getIDTreeAsMap(kid));
-            }
-        }
-        return names;
-    }
-
     // PDNumberTreeNode.getNumbers() only brings one level, this is why we need this
     // might be made public at a later time, or integrated into PDNumberTreeNode.
     static Map<Integer, COSObjectable> getNumberTreeAsMap(PDNumberTreeNode tree)

Modified: pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/Splitter.java
==============================================================================
--- pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/Splitter.java	Wed Oct  7 14:17:00 2026	(r1938855)
+++ pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/Splitter.java	Wed Oct  7 14:20:40 2026	(r1938856)
@@ -257,7 +257,7 @@ public class Splitter
         {
             return;
         }
-        Map<String, PDStructureElement> srcIDTreeAsMap = PDFMergerUtility.getIDTreeAsMap(srcIDTree);
+        Map<String, PDStructureElement> srcIDTreeAsMap = srcIDTree.getTreeAsMap();
         Map<String, PDStructureElement> destNames = new HashMap<>();
         srcIDTreeAsMap.forEach((key, val) ->
         {

Modified: pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/PDNameTreeNode.java
==============================================================================
--- pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/PDNameTreeNode.java	Wed Oct  7 14:17:00 2026	(r1938855)
+++ pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/PDNameTreeNode.java	Wed Oct  7 14:20:40 2026	(r1938856)
@@ -252,7 +252,7 @@ public abstract class PDNameTreeNode<T e
     }
 
     /**
-     * This will return a map of names on this level. The key will be a string,
+     * This will return a map of names on THIS level. The key will be a string,
      * and the value will depend on where this class is being used.
      *
      * @return ordered map of COS objects or <code>null</code> if the dictionary
@@ -405,4 +405,35 @@ public abstract class PDNameTreeNode<T e
         }
         arr.setString( 0, lower );
     }
+
+    /**
+     * This will get a map of names on ALL levels. The key will be a string,
+     * and the value will depend on where this class is being used.
+     *
+     * @return ordered map of COS objects, never null.
+     *
+     * @throws IOException If there is an error while creating the sub types.
+     */
+    public Map<String, T> getTreeAsMap() throws IOException
+    {
+        Map<String, T> names = getNames();
+        if (getNames() == null)
+        {
+            names = new LinkedHashMap<>();
+        }
+        else
+        {
+            // must copy because the map is read only
+            names = new LinkedHashMap<>(names);
+        }
+        List<PDNameTreeNode<T>> kids = getKids();
+        if (kids != null)
+        {
+            for (PDNameTreeNode<T> kid : kids)
+            {
+                names.putAll(kid.getTreeAsMap());
+            }
+        }
+        return names;
+    }
 }

Modified: pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java
==============================================================================
--- pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java	Wed Oct  7 14:17:00 2026	(r1938855)
+++ pdfbox/branches/3.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java	Wed Oct  7 14:20:40 2026	(r1938856)
@@ -547,9 +547,9 @@ class PDFMergerUtilityTest
         PDDocument dst = Loader.loadPDF(new File(SRCDIR, "PDFBOX-4417-054080.pdf"));
 
         PDNameTreeNode<PDStructureElement> srcIDTree = src.getDocumentCatalog().getStructureTreeRoot().getIDTree();
-        Map<String, PDStructureElement> srcIDTreeMap = PDFMergerUtility.getIDTreeAsMap(srcIDTree);
+        Map<String, PDStructureElement> srcIDTreeMap = srcIDTree.getTreeAsMap();
         PDNameTreeNode<PDStructureElement> dstIDTree = dst.getDocumentCatalog().getStructureTreeRoot().getIDTree();
-        Map<String, PDStructureElement> dstIDTreeMap = PDFMergerUtility.getIDTreeAsMap(dstIDTree);
+        Map<String, PDStructureElement> dstIDTreeMap = dstIDTree.getTreeAsMap();
         int expectedTotal = srcIDTreeMap.size() + dstIDTreeMap.size();
         assertEquals(192, expectedTotal);
 
@@ -570,7 +570,7 @@ class PDFMergerUtilityTest
         checkForPageOrphans(dst);
 
         dstIDTree = dst.getDocumentCatalog().getStructureTreeRoot().getIDTree();
-        dstIDTreeMap = PDFMergerUtility.getIDTreeAsMap(dstIDTree);
+        dstIDTreeMap = dstIDTree.getTreeAsMap();
         assertEquals(expectedTotal, dstIDTreeMap.size());
 
         dst.close();
@@ -900,11 +900,16 @@ class PDFMergerUtilityTest
         // StructTreeRoot/IDTree trees.
         PDPageTree pageTree = doc.getPages();
         PDStructureTreeRoot structureTreeRoot = doc.getDocumentCatalog().getStructureTreeRoot();
-        Map<String, PDStructureElement> idTreeMap = PDFMergerUtility.getIDTreeAsMap(structureTreeRoot.getIDTree());
+        PDNameTreeNode<PDStructureElement> idTree = structureTreeRoot.getIDTree();
+        Map<String, PDStructureElement> idTreeMap = Collections.emptyMap();
+        if (idTree != null)
+        {
+            idTreeMap = idTree.getTreeAsMap();
+        }
         checkElement(pageTree, structureTreeRoot.getParentTree().getCOSObject(), structureTreeRoot.getCOSObject(), idTreeMap);
         assertNotNull(structureTreeRoot.getK());
         checkElement(pageTree, structureTreeRoot.getK(), structureTreeRoot.getCOSObject(), idTreeMap);
-        checkForIDTreeOrphans(pageTree, PDFMergerUtility.getIDTreeAsMap(structureTreeRoot.getIDTree()));
+        checkForIDTreeOrphans(pageTree, idTreeMap);
         checkParentTreeAgainstK(structureTreeRoot);
     }
 
@@ -1247,7 +1252,7 @@ class PDFMergerUtilityTest
                 // these tests just verify the status quo. Changes should be checked visually with
                 // a PDF viewer that can display structural information.
                 PDStructureTreeRoot structureTreeRoot = dstDoc.getDocumentCatalog().getStructureTreeRoot();
-                assertEquals(126, PDFMergerUtility.getIDTreeAsMap(structureTreeRoot.getIDTree()).size());
+                assertEquals(126, structureTreeRoot.getIDTree().getTreeAsMap().size());
                 assertEquals(2, PDFMergerUtility.getNumberTreeAsMap(structureTreeRoot.getParentTree()).size());
                 assertEquals(6, structureTreeRoot.getRoleMap().size());
             }