Skip to content

Commit

Permalink
close torakiki#198: populate bookmarks combo level with all the valid…
Browse files Browse the repository at this point in the history
… levels

Even incase they are not contiguos
  • Loading branch information
torakiki committed Oct 23, 2016
1 parent 7ef7e28 commit 131aabe
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,25 @@
*/
package org.pdfsam.pdf;

import static java.util.Objects.nonNull;
import static java.util.Optional.ofNullable;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.pdfsam.support.RequireUtils.requireNotNull;

import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang3.StringUtils;
import org.pdfsam.support.ObservableAtomicReference;
import org.sejda.model.input.PdfFileSource;
import org.sejda.model.pdf.PdfVersion;

/**
* Lightweight pdf document descriptor holding data necessary to fill the selection table and request a task execution.
*
Expand All @@ -47,7 +53,7 @@ public class PdfDocumentDescriptor {
private File file;
private PdfVersion version;
private Map<String, String> metadata = new HashMap<>();
private int maxGoToActionDepth = 0;
private SortedSet<Integer> validBookmarksLevels = Collections.emptySortedSet();

private PdfDocumentDescriptor(File file, String password) {
requireNotNull(file, "Input file is mandatory");
Expand Down Expand Up @@ -129,12 +135,15 @@ public File getFile() {
return file;
}

public void setMaxGoToActionDepth(int maxGoToActionDepth) {
this.maxGoToActionDepth = maxGoToActionDepth;
public void setValidBookmarksLevels(Set<Integer> levels) {
this.validBookmarksLevels = new TreeSet<>();
if (nonNull(levels)) {
levels.stream().forEach(this.validBookmarksLevels::add);
}
}

public int getMaxGoToActionDepth() {
return maxGoToActionDepth;
public SortedSet<Integer> getValidBookmarksLevels() {
return validBookmarksLevels;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* This file is part of the PDF Split And Merge source code
* Created on 22 ott 2016
* Copyright 2013-2014 by Andrea Vacondio ([email protected]).
*
* This program 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.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.pdfsam.support.validation;

import static java.util.Optional.ofNullable;

import java.util.HashSet;
import java.util.Set;

/**
* Validates that a given String represent an integer in a given set
*
* @author Andrea Vacondio
*
*/
public class ContainedIntegerValidator implements Validator<String> {
private Set<Integer> valid = new HashSet<>();

public ContainedIntegerValidator(Set<Integer> validValues) {
ofNullable(validValues).map(valid::addAll);
}

@Override
public boolean isValid(String input) {
try {
return valid.contains(Integer.parseInt(input));
} catch (NumberFormatException e) {
// not a valid integer
return false;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Set;

import org.pdfsam.support.io.FileType;

Expand Down Expand Up @@ -67,6 +68,13 @@ public static Validator<String> positiveIntRange(int lower, int upper) {
return new PositiveIntRangeStringValidator(lower, upper);
}

/**
* @return a new instance of a validator checking for a input string representing an integer contained in the given set
*/
public static Validator<String> containedInteger(Set<Integer> validValues) {
return new ContainedIntegerValidator(validValues);
}

/**
* @return a new instance of a validator checking for an input string representing an existing file. Blank string are invalid.
* @see Validators#validEmpty(Validator)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* This file is part of the PDF Split And Merge source code
* Created on 22 ott 2016
* Copyright 2013-2014 by Andrea Vacondio ([email protected]).
*
* This program 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.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.pdfsam.support.validation;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.HashSet;

import org.junit.Test;

/**
* @author Andrea Vacondio
*
*/
public class ContainedIntegerValidatorTest {
private Validator<String> victim = Validators.containedInteger(new HashSet<>(Arrays.asList(-2, 5, 6)));

@Test
public void testNotContained() {
assertFalse(victim.isValid("50"));
}

@Test
public void testInvalid() {
assertFalse(victim.isValid("dsdsa"));
}

@Test
public void testValid() {
assertTrue(victim.isValid("5"));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class BookmarksLevelSAMBoxLoader implements PdfLoader<PDDocument> {

@Override
public void accept(PDDocument document, PdfDocumentDescriptor descriptor) {
descriptor.setMaxGoToActionDepth(OutlineUtils.getMaxOutlineLevel(document));
descriptor.setValidBookmarksLevels(OutlineUtils.getOutlineLevelsWithPageDestination(document));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@
*/
package org.pdfsam.pdf;

import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import java.io.IOException;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import org.sejda.common.ComponentsUtility;
import org.sejda.io.SeekableSources;
import org.sejda.sambox.input.PDFParser;
Expand All @@ -47,8 +51,8 @@ public class BookmarksLevelSAMBoxLoaderTest {
@Before
public void setUp() throws IOException {
descriptor = mock(PdfDocumentDescriptor.class);
document = PDFParser.parse(SeekableSources.inMemorySeekableSourceFrom(getClass().getResourceAsStream(
"/test_outline.pdf")));
document = PDFParser
.parse(SeekableSources.inMemorySeekableSourceFrom(getClass().getResourceAsStream("/test_outline.pdf")));
}

@After
Expand All @@ -59,6 +63,8 @@ public void tearDown() {
@Test
public void accept() {
new BookmarksLevelSAMBoxLoader().accept(document, descriptor);
verify(descriptor).setMaxGoToActionDepth(3);
ArgumentCaptor<Set> captor = ArgumentCaptor.forClass(Set.class);
verify(descriptor).setValidBookmarksLevels(captor.capture());
assertThat((Set<Integer>) captor.getValue(), hasItems(1, 2, 3));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@
import static java.util.Objects.nonNull;
import static java.util.Optional.ofNullable;

import java.util.Arrays;
import java.util.Map;
import java.util.SortedSet;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.pdfsam.i18n.DefaultI18nContext;
import org.pdfsam.support.params.TaskParametersBuildStep;
Expand Down Expand Up @@ -68,13 +72,11 @@ class BookmarksLevelComboBox extends ComboBox<String>
});
}

public void setMaxBookmarkLevel(int max) {
public void setValidBookmarkLevels(SortedSet<Integer> levels) {
getItems().clear();
if (max > 0) {
validationSupport.setValidator(Validators.positiveIntRange(1, max));
for (int i = 1; i <= max; i++) {
getItems().add(Integer.toString(i));
}
if (nonNull(levels)) {
validationSupport.setValidator(Validators.containedInteger(levels));
levels.stream().map(i -> i.toString()).forEach(getItems()::add);
} else {
validationSupport.setValidator(Validators.alwaysFalse());
}
Expand Down Expand Up @@ -107,14 +109,18 @@ public void apply(SplitByOutlineLevelParametersBuilder builder, Consumer<String>

@Override
public void saveStateTo(Map<String, String> data) {
data.put("levelCombo.max", Integer.toString(getItems().size()));
data.put("levelCombo.levels", getItems().stream().collect(Collectors.joining(",")));
data.put("levelCombo.selected", ofNullable(getValue()).orElse(""));
}

@Override
public void restoreStateFrom(Map<String, String> data) {
getSelectionModel().selectFirst();
ofNullable(data.get("levelCombo.max")).map(Integer::valueOf).ifPresent(this::setMaxBookmarkLevel);
ofNullable(data.get("levelCombo.max")).map(Integer::valueOf).ifPresent(max -> {
IntStream.rangeClosed(1, max).mapToObj(Integer::toString).forEach(getItems()::add);
});
Arrays.stream(ofNullable(data.get("levelCombo.levels")).map(l -> l.split(",")).orElse(new String[0]))
.forEach(getItems()::add);
setValue(ofNullable(data.get("levelCombo.selected")).orElse(""));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public SplitByBookmarksModule(@Named(MODULE_ID + "field") BrowsableOutputDirecto
this.selectionPane = new TaskParametersBuilderSingleSelectionPane(id());
this.selectionPane.setPromptText(
DefaultI18nContext.getInstance().i18n("Select or drag and drop the PDF you want to split"));
this.selectionPane.addOnLoaded(d -> splitOptions.setMaxBookmarkLevel(d.getMaxGoToActionDepth()));
this.selectionPane.addOnLoaded(d -> splitOptions.setValidBookmarkLevels(d.getValidBookmarksLevels()));

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import java.util.Map;
import java.util.Optional;
import java.util.SortedSet;
import java.util.function.Consumer;

import org.pdfsam.i18n.DefaultI18nContext;
Expand Down Expand Up @@ -63,15 +64,14 @@ class SplitOptionsPane extends VBox
regexpField.setPrefWidth(350);
getChildren().addAll(createLine(new Label(ctx.i18n("Split at this bookmark level:")), levelCombo),
createLine(new Label(ctx.i18n("Matching regular expression:")), regexpField,
helpIcon(new TextFlow(
new Text(ctx.i18n("A regular expression the bookmark text has to match")
+ System.lineSeparator()),
helpIcon(new TextFlow(new Text(ctx.i18n("A regular expression the bookmark text has to match")
+ System.lineSeparator()),
new Text(ctx.i18n(
"Example: use .*Chapter.* to match bookmarks containing the word \"Chapter\""))))));
}

void setMaxBookmarkLevel(int max) {
levelCombo.setMaxBookmarkLevel(max);
void setValidBookmarkLevels(SortedSet<Integer> levels) {
levelCombo.setValidBookmarkLevels(levels);
}

private HBox createLine(Node... items) {
Expand Down
Loading

0 comments on commit 131aabe

Please sign in to comment.