diff --git a/src/main/java/net/sf/jabref/gui/actions/CleanUpAction.java b/src/main/java/net/sf/jabref/gui/actions/CleanUpAction.java index 94cd4f0e4e7..6491ebe6d9e 100644 --- a/src/main/java/net/sf/jabref/gui/actions/CleanUpAction.java +++ b/src/main/java/net/sf/jabref/gui/actions/CleanUpAction.java @@ -41,6 +41,8 @@ import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; +import net.sf.jabref.logic.cleanup.PageNumbersCleanup; +import net.sf.jabref.logic.formatter.FieldFormatters; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibtexEntry; import net.sf.jabref.logic.util.DOI; @@ -445,12 +447,12 @@ private static void doCleanUpMonth(BibtexEntry entry, NamedCompound ce) { private static void doCleanUpPageNumbers(BibtexEntry entry, NamedCompound ce) { String oldValue = entry.getField("pages"); - if (oldValue == null) { - return; - } - String newValue = oldValue.replaceAll(" *(\\d+) *- *(\\d+) *", "$1--$2"); - if (!oldValue.equals(newValue)) { - entry.setField("pages", newValue); + // run formatter + new PageNumbersCleanup(entry).cleanup(); + // new value + String newValue = entry.getField("pages"); + // undo action + if(!oldValue.equals(newValue)) { ce.addEdit(new UndoableFieldChange(entry, "pages", oldValue, newValue)); } } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/PageNumbersCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/PageNumbersCleanup.java new file mode 100644 index 00000000000..7e7d197f1ba --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/cleanup/PageNumbersCleanup.java @@ -0,0 +1,30 @@ +package net.sf.jabref.logic.cleanup; + +import net.sf.jabref.logic.formatter.FieldFormatters; +import net.sf.jabref.logic.formatter.PageNumbersFormatter; +import net.sf.jabref.model.entry.BibtexEntry; + +/** + * This class includes sensible defaults for consistent formatting of BibTex page numbers. + */ +public class PageNumbersCleanup { + private BibtexEntry entry; + + public PageNumbersCleanup(BibtexEntry entry) { + this.entry = entry; + } + + /** + * Format page numbers, separated either by commas or double-hyphens. + * Converts the range number format of the pages field to page_number--page_number. + * + * @see{PageNumbersFormatter} + */ + public void cleanup() { + final String field = "pages"; + + String value = entry.getField(field); + String newValue = FieldFormatters.PAGE_NUMBERS.format(value); + entry.setField(field, newValue); + } +} diff --git a/src/main/java/net/sf/jabref/logic/formatter/FieldFormatters.java b/src/main/java/net/sf/jabref/logic/formatter/FieldFormatters.java new file mode 100644 index 00000000000..9957ebd5829 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/formatter/FieldFormatters.java @@ -0,0 +1,10 @@ +package net.sf.jabref.logic.formatter; + +import java.util.Arrays; +import java.util.List; + +public class FieldFormatters { + public static final PageNumbersFormatter PAGE_NUMBERS = new PageNumbersFormatter(); + + public static final List ALL = Arrays.asList(PAGE_NUMBERS); +} diff --git a/src/main/java/net/sf/jabref/logic/formatter/Formatter.java b/src/main/java/net/sf/jabref/logic/formatter/Formatter.java new file mode 100644 index 00000000000..e55631184bd --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/formatter/Formatter.java @@ -0,0 +1,21 @@ +package net.sf.jabref.logic.formatter; + +/** + * Formatter Interface + */ +public interface Formatter { + /** + * Returns a human readable name of the formatter usable for e.g. in the GUI + * + * @return the name of the formatter + */ + String getName(); + + /** + * Formats a field value by with a particular formatter transformation. + * + * @param value the input String + * @return the formatted output String + */ + String format(String value); +} diff --git a/src/main/java/net/sf/jabref/logic/formatter/PageNumbersFormatter.java b/src/main/java/net/sf/jabref/logic/formatter/PageNumbersFormatter.java new file mode 100644 index 00000000000..00f81e918b4 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/formatter/PageNumbersFormatter.java @@ -0,0 +1,51 @@ +package net.sf.jabref.logic.formatter; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * This class includes sensible defaults for consistent formatting of BibTex page numbers. + */ +public class PageNumbersFormatter implements Formatter { + @Override + public String getName() { + return "Page numbers"; + } + + /** + * Format page numbers, separated either by commas or double-hyphens. + * Converts the range number format of the pages field to page_number--page_number. + * Removes all literals except [0-9,-]. + * Keeps the existing String if the resulting field does not match the expected Regex. + * + * + * 1-2 -> 1--2 + * 1,2,3 -> 1,2,3 + * {1}-{2} -> 1--2 + * Invalid -> Invalid + * + */ + public String format(String value) { + final String rejectLiterals = "[^0-9,-]"; + final Pattern pagesPattern = Pattern.compile("\\A(\\d+)-{1,2}(\\d+)\\Z"); + final String replace = "$1--$2"; + + // nothing to do + if (value == null || value.isEmpty()) { + return value; + } + + // remove unwanted literals incl. whitespace + String cleanValue = value.replaceAll(rejectLiterals, ""); + // try to find pages pattern + Matcher matcher = pagesPattern.matcher(cleanValue); + // replace + String newValue = matcher.replaceFirst(replace); + // replacement? + if(!newValue.equals(cleanValue)) { + // write field + return newValue; + } + return value; + } +} diff --git a/src/test/java/net/sf/jabref/logic/cleanup/PageNumbersCleanupTest.java b/src/test/java/net/sf/jabref/logic/cleanup/PageNumbersCleanupTest.java new file mode 100644 index 00000000000..53ededba9ef --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/cleanup/PageNumbersCleanupTest.java @@ -0,0 +1,39 @@ +package net.sf.jabref.logic.cleanup; + +import junit.framework.Assert; +import net.sf.jabref.model.entry.BibtexEntry; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PageNumbersCleanupTest { + private BibtexEntry entry; + + @Before + public void setUp() { + entry = new BibtexEntry(); + } + + @After + public void teardown() { + entry = null; + } + + @Test + public void formatPageNumbers() { + entry.setField("pages", "1-2"); + new PageNumbersCleanup(entry).cleanup(); + + Assert.assertEquals("1--2", entry.getField("pages")); + } + + @Test + public void onlyFormatPageNumbersField() { + entry.setField("otherfield", "1-2"); + new PageNumbersCleanup(entry).cleanup(); + + Assert.assertEquals("1-2", entry.getField("otherfield")); + } +} \ No newline at end of file diff --git a/src/test/java/net/sf/jabref/logic/formatter/PageNumbersFormatterTest.java b/src/test/java/net/sf/jabref/logic/formatter/PageNumbersFormatterTest.java new file mode 100644 index 00000000000..d3decb3b106 --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/formatter/PageNumbersFormatterTest.java @@ -0,0 +1,62 @@ +package net.sf.jabref.logic.formatter; + +import junit.framework.Assert; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PageNumbersFormatterTest { + private PageNumbersFormatter formatter; + + @Before + public void setUp() { + formatter = new PageNumbersFormatter(); + } + + @After + public void teardown() { + formatter = null; + } + + @Test + public void formatPageNumbers() { + expectCorrect("1-2", "1--2"); + } + + @Test + public void formatPageNumbersCommaSeparated() { + expectCorrect("1,2,3", "1,2,3"); + } + + @Test + public void ignoreWhitespaceInPageNumbers() { + expectCorrect(" 1 - 2 ", "1--2"); + } + + @Test + public void keepCorrectlyFormattedPageNumbers() { + expectCorrect("1--2", "1--2"); + } + + @Test + public void formatPageNumbersEmptyFields() { + expectCorrect("", ""); + expectCorrect(null, null); + } + + @Test + public void formatPageNumbersRemoveUnexpectedLiterals() { + expectCorrect("{1}-{2}", "1--2"); + } + + @Test + public void formatPageNumbersRegexNotMatching() { + expectCorrect("12", "12"); + } + + private void expectCorrect(String input, String expected) { + Assert.assertEquals(expected, formatter.format(input)); + } +} \ No newline at end of file