/*
* Created on 16/ago/2015
* Copyright 2015 by Andrea Vacondio (andrea.vacondio@gmail.com).
* This file is part of Sejda.
*
* Sejda is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sejda is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Sejda. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sejda.impl.sambox.component;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import org.sejda.io.SeekableSources;
import org.sejda.sambox.input.PDFParser;
import org.sejda.sambox.pdmodel.PDDocument;
import org.sejda.sambox.pdmodel.PDDocumentCatalog;
import org.sejda.sambox.pdmodel.PDPage;
import org.sejda.sambox.pdmodel.interactive.action.PDActionGoTo;
import org.sejda.sambox.pdmodel.interactive.documentnavigation.destination.PDNamedDestination;
import org.sejda.sambox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
import org.sejda.sambox.pdmodel.interactive.documentnavigation.destination.PDPageFitDestination;
import org.sejda.sambox.pdmodel.interactive.documentnavigation.destination.PDPageFitHeightDestination;
import org.sejda.sambox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
import org.sejda.sambox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
/**
* @author Andrea Vacondio
*
*/
public class OutlineUtilsTest {
@Test
public void toPageDestinationEmpty() {
PDOutlineItem victim = new PDOutlineItem();
assertFalse(OutlineUtils.toPageDestination(victim, null).isPresent());
}
@Test
public void toPageDestinationAction() {
PDPageFitDestination destination = new PDPageFitDestination();
PDPage page = new PDPage();
destination.setPage(page);
PDActionGoTo action = new PDActionGoTo();
action.setDestination(destination);
PDOutlineItem victim = new PDOutlineItem();
victim.setAction(action);
assertEquals(destination.getPage(), OutlineUtils.toPageDestination(victim, null).get().getPage());
}
@Test
public void toPageDestinationDestination() {
PDPageFitDestination destination = new PDPageFitDestination();
destination.setPageNumber(5);
PDOutlineItem victim = new PDOutlineItem();
victim.setDestination(destination);
PDDocumentCatalog catalog = mock(PDDocumentCatalog.class);
assertEquals(5, OutlineUtils.toPageDestination(victim, catalog).get().getPageNumber());
}
@Test
public void toPageDestinationDestinationNullCatalog() {
PDPageFitDestination dest = new PDPageFitDestination();
dest.setPageNumber(5);
PDNamedDestination destination = new PDNamedDestination();
destination.setNamedDestination("ChuckNorris");
PDOutlineItem victim = new PDOutlineItem();
victim.setDestination(destination);
PDDocumentCatalog catalog = null;
assertFalse(OutlineUtils.toPageDestination(victim, catalog).isPresent());
}
@Test
public void toPageDestinationNamedDestinationNullNames() {
PDNamedDestination destination = new PDNamedDestination();
PDOutlineItem victim = new PDOutlineItem();
victim.setDestination(destination);
assertFalse(OutlineUtils.toPageDestination(victim, null).isPresent());
}
@Test
public void toPageDestinationNamedDestination() throws IOException {
PDPageFitDestination dest = new PDPageFitDestination();
dest.setPageNumber(5);
PDNamedDestination destination = new PDNamedDestination();
destination.setNamedDestination("ChuckNorris");
PDOutlineItem victim = new PDOutlineItem();
victim.setDestination(destination);
PDDocumentCatalog catalog = mock(PDDocumentCatalog.class);
when(catalog.findNamedDestinationPage(any())).thenReturn(dest);
assertEquals(dest, OutlineUtils.toPageDestination(victim, catalog).get());
}
@Test(expected = IllegalArgumentException.class)
public void clonePageDestinationNullDest() {
OutlineUtils.clonePageDestination(null, new PDPage());
}
@Test
public void clonePageDestinationSameType() {
PDPage origin = new PDPage();
PDPage newPage = new PDPage();
PDPageFitHeightDestination destination = new PDPageFitHeightDestination();
destination.setPage(origin);
destination.setLeft(20);
PDPageDestination cloned = OutlineUtils.clonePageDestination(destination, newPage);
assertThat(cloned, is(instanceOf(PDPageFitHeightDestination.class)));
assertEquals(newPage, cloned.getPage());
assertEquals(20, ((PDPageFitHeightDestination) cloned).getLeft());
}
@Test
public void copyDictionary() {
PDOutlineItem from = new PDOutlineItem();
from.setBold(true);
from.setItalic(true);
from.setTitle("Chuck");
PDOutlineItem to = new PDOutlineItem();
to.setBold(false);
to.setItalic(false);
OutlineUtils.copyOutlineDictionary(from, to);
assertTrue(to.isBold());
assertTrue(to.isItalic());
assertEquals("Chuck", to.getTitle());
}
@Test
// title is required by the spec
public void copyDictionaryFixesNullTitles() {
PDOutlineItem from = new PDOutlineItem();
from.setTitle(null);
PDOutlineItem to = new PDOutlineItem();
assertNull(from.getTitle());
OutlineUtils.copyOutlineDictionary(from, to);
assertNotNull(to.getTitle());
}
@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 outlineLevels() throws IOException {
try (PDDocument doc = PDFParser.parse(
SeekableSources.inMemorySeekableSourceFrom(getClass().getResourceAsStream("/pdf/test_outline.pdf")))) {
Set<Integer> levels = OutlineUtils.getOutlineLevelsWithPageDestination(doc);
assertEquals(3, levels.size());
assertTrue(levels.contains(1));
assertTrue(levels.contains(2));
assertTrue(levels.contains(3));
}
}
@Test
public void outlineLevelsParentHasNoPageDest() {
PDPage page1 = new PDPage();
PDDocument document = new PDDocument();
document.addPage(page1);
PDDocumentOutline outlines = new PDDocumentOutline();
PDOutlineItem root = new PDOutlineItem();
root.setTitle("title");
PDOutlineItem child = new PDOutlineItem();
child.setTitle("child");
PDOutlineItem child2 = new PDOutlineItem();
child2.setTitle("child2");
child2.setDestination(page1);
child.addFirst(child2);
root.addLast(child);
outlines.addFirst(root);
document.getDocumentCatalog().setDocumentOutline(outlines);
Set<Integer> levels = OutlineUtils.getOutlineLevelsWithPageDestination(document);
assertEquals(1, levels.size());
assertTrue(levels.contains(3));
}
@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);
}
}