OutlineUtils { public static List<OutlineItem> getFlatOutline(PDDocument document) { return ofNullable(document.getDocumentCatalog().getDocumentOutline()).map(PDDocumentOutline::children) .map(c -> recurseFlatOutline(document, c, 1)).orElseGet(ArrayList::new).stream() .sorted(Comparator.comparingInt(i -> i.page)).filter(i -> i.page > 0).collect(Collectors.toList()); } private  OutlineUtils(); static Set<Integer> getOutlineLevelsWithPageDestination(PDDocument document); static Optional<PDPageDestination> toPageDestination(PDOutlineItem current, PDDocumentCatalog catalog); static PDPageXYZDestination pageDestinationFor(PDPage page); static PDPageDestination clonePageDestination(PDPageDestination dest, PDPage destPage); static PDPage resolvePageDestination(PDPageDestination destination, PDDocument document); static void copyOutlineDictionary(PDOutlineItem from, PDOutlineItem to); static List<OutlineItem> getFlatOutline(PDDocument document); static void printOutline(PDDocument document);  }
@Test public void noOutlineFlat() throws IOException { try (PDDocument doc = PDFParser.parse(SeekableSources .inMemorySeekableSourceFrom(getClass().getResourceAsStream("/pdf/test_no_outline.pdf")))) { assertTrue(OutlineUtils.getFlatOutline(doc).isEmpty()); } }
@Test public void outlineFlat() throws IOException { try (PDDocument doc = PDFParser.parse( SeekableSources.inMemorySeekableSourceFrom(getClass().getResourceAsStream("/pdf/test_outline.pdf")))) { assertEquals(5, OutlineUtils.getFlatOutline(doc).size()); } }
@Test public void outlineFlatIntPageDestinations() throws IOException { try (PDDocument doc = PDFParser.parse(SeekableSources .inMemorySeekableSourceFrom(getClass().getResourceAsStream("/pdf/destination_pages_as_int.pdf")))) { List<OutlineItem> flatOutline = OutlineUtils.getFlatOutline(doc); assertEquals(5, flatOutline.size()); assertEquals(1, flatOutline.get(0).page); assertEquals(1, flatOutline.get(1).page); assertEquals(3, flatOutline.get(2).page); assertEquals(3, flatOutline.get(3).page); assertEquals(5, flatOutline.get(4).page); } }
@Test public void rootNoDestinationAndSorted() { PDPage page1 = new PDPage(); PDPage page2 = new PDPage(); PDDocument document = new PDDocument(); document.addPage(page1); document.addPage(page2); PDDocumentOutline outlines = new PDDocumentOutline(); PDOutlineItem root = new PDOutlineItem(); root.setTitle("title"); PDOutlineItem child = new PDOutlineItem(); child.setTitle("child"); child.setDestination(page2); PDOutlineItem child2 = new PDOutlineItem(); child2.setTitle("child2"); child2.setDestination(page1); root.addFirst(child); root.addLast(child2); outlines.addFirst(root); document.getDocumentCatalog().setDocumentOutline(outlines); List<OutlineItem> flat = OutlineUtils.getFlatOutline(document); assertEquals(2, flat.size()); assertEquals("child2", flat.get(0).title); }