From f62c8c16d11415e9591cb2e5ffa69c916776e851 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Wed, 28 Dec 2016 17:14:21 +0100 Subject: [PATCH 1/2] Group all checker which only check the value of one field --- .../logic/integrity/AbbreviationChecker.java | 17 +++-------- .../logic/integrity/BiblatexPagesChecker.java | 16 ++++------ .../logic/integrity/BooktitleChecker.java | 18 +++++------ .../logic/integrity/BracketChecker.java | 19 +++--------- .../logic/integrity/DOIValidityChecker.java | 19 +++++++----- .../logic/integrity/EditionChecker.java | 16 ++++------ .../jabref/logic/integrity/FieldChecker.java | 27 +++++++++++++++++ .../jabref/logic/integrity/FileChecker.java | 14 ++++----- .../logic/integrity/HowpublishedChecker.java | 14 +++------ .../jabref/logic/integrity/ISBNChecker.java | 16 +++++----- .../jabref/logic/integrity/ISSNChecker.java | 15 ++++------ .../jabref/logic/integrity/MonthChecker.java | 16 ++++------ .../jabref/logic/integrity/NoteChecker.java | 14 +++------ .../jabref/logic/integrity/PagesChecker.java | 16 ++++------ .../jabref/logic/integrity/TitleChecker.java | 30 ++++++++----------- .../sf/jabref/logic/integrity/UrlChecker.java | 17 +++++------ .../jabref/logic/integrity/YearChecker.java | 18 +++++------ 17 files changed, 128 insertions(+), 174 deletions(-) create mode 100644 src/main/java/net/sf/jabref/logic/integrity/FieldChecker.java diff --git a/src/main/java/net/sf/jabref/logic/integrity/AbbreviationChecker.java b/src/main/java/net/sf/jabref/logic/integrity/AbbreviationChecker.java index 2935a6d94be..3de0e11f12f 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/AbbreviationChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/AbbreviationChecker.java @@ -2,29 +2,20 @@ import java.util.Collections; import java.util.List; -import java.util.Optional; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; -public class AbbreviationChecker implements Checker { - - private final String field; +public class AbbreviationChecker extends FieldChecker { public AbbreviationChecker(String field) { - this.field = field; + super(field); } @Override - public List check(BibEntry entry) { - Optional value = entry.getField(field); - if (!value.isPresent()) { - return Collections.emptyList(); - } - - if (value.get().contains(".")) { + protected List checkValue(String value, BibEntry entry) { + if (value.contains(".")) { return Collections .singletonList(new IntegrityMessage(Localization.lang("abbreviation detected"), entry, field)); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/BiblatexPagesChecker.java b/src/main/java/net/sf/jabref/logic/integrity/BiblatexPagesChecker.java index 3f032527c32..0ceb91a177b 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/BiblatexPagesChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/BiblatexPagesChecker.java @@ -2,11 +2,9 @@ import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -14,7 +12,7 @@ /** * Same as {@link PagesChecker} but allows single dash as well */ -public class BiblatexPagesChecker implements Checker { +public class BiblatexPagesChecker extends FieldChecker { private static final String PAGES_EXP = "" + "\\A" // begin String + "\\d+" // number @@ -29,18 +27,16 @@ public class BiblatexPagesChecker implements Checker { private static final Predicate VALID_PAGE_NUMBER = Pattern.compile(PAGES_EXP).asPredicate(); + public BiblatexPagesChecker() { + super(FieldName.PAGES); + } /** * Checks, if the page numbers String conforms to the BibTex manual */ @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.PAGES); - if (!value.isPresent()) { - return Collections.emptyList(); - } - - if (!VALID_PAGE_NUMBER.test(value.get().trim())) { + protected List checkValue(String value, BibEntry entry) { + if (!VALID_PAGE_NUMBER.test(value.trim())) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should contain a valid page number range"), entry, FieldName.PAGES)); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/BooktitleChecker.java b/src/main/java/net/sf/jabref/logic/integrity/BooktitleChecker.java index 4f8b02a001a..0f2ba5e0747 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/BooktitleChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/BooktitleChecker.java @@ -3,24 +3,20 @@ import java.util.Collections; import java.util.List; import java.util.Locale; -import java.util.Optional; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class BooktitleChecker implements Checker { +public class BooktitleChecker extends FieldChecker { - @Override - public List check(BibEntry entry) { - String field = FieldName.BOOKTITLE; - Optional value = entry.getField(field); - if (!value.isPresent()) { - return Collections.emptyList(); - } + public BooktitleChecker() { + super(FieldName.BOOKTITLE); + } - if (value.get().toLowerCase(Locale.ENGLISH).endsWith("conference on")) { + @Override + protected List checkValue(String value, BibEntry entry) { + if (value.toLowerCase(Locale.ENGLISH).endsWith("conference on")) { return Collections.singletonList( new IntegrityMessage(Localization.lang("booktitle ends with 'conference on'"), entry, field)); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/BracketChecker.java b/src/main/java/net/sf/jabref/logic/integrity/BracketChecker.java index 94d79ac7c94..bf7ce8d2f05 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/BracketChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/BracketChecker.java @@ -2,31 +2,21 @@ import java.util.Collections; import java.util.List; -import java.util.Optional; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; -public class BracketChecker implements Checker { - - private final String field; - +public class BracketChecker extends FieldChecker { public BracketChecker(String field) { - this.field = field; + super(field); } @Override - public List check(BibEntry entry) { - Optional value = entry.getField(field); - if (!value.isPresent()) { - return Collections.emptyList(); - } - + protected List checkValue(String value, BibEntry entry) { // metaphor: integer-based stack (push + / pop -) int counter = 0; - for (char a : value.get().trim().toCharArray()) { + for (char a : value.trim().toCharArray()) { if (a == '{') { counter++; } else if (a == '}') { @@ -46,5 +36,4 @@ public List check(BibEntry entry) { return Collections.emptyList(); } - } diff --git a/src/main/java/net/sf/jabref/logic/integrity/DOIValidityChecker.java b/src/main/java/net/sf/jabref/logic/integrity/DOIValidityChecker.java index ebcdd335c4f..7db74aa8746 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/DOIValidityChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/DOIValidityChecker.java @@ -3,20 +3,23 @@ import java.util.Collections; import java.util.List; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.DOI; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class DOIValidityChecker implements Checker { +public class DOIValidityChecker extends FieldChecker { + + public DOIValidityChecker() { + super(FieldName.DOI); + } @Override - public List check(BibEntry entry) { - final String field = FieldName.DOI; - return entry.getField(field) - .filter(d -> !DOI.isValid(d)) - .map(d -> Collections.singletonList(new IntegrityMessage(Localization.lang("DOI %0 is invalid", d), entry, field))) - .orElse(Collections.emptyList()); + protected List checkValue(String value, BibEntry entry) { + if (DOI.isValid(value)) { + return Collections.emptyList(); + } else { + return Collections.singletonList(new IntegrityMessage(Localization.lang("DOI %0 is invalid", value), entry, field)); + } } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/EditionChecker.java b/src/main/java/net/sf/jabref/logic/integrity/EditionChecker.java index eb2f0e4434c..4c4dada35be 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/EditionChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/EditionChecker.java @@ -3,17 +3,15 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseContext; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class EditionChecker implements Checker { +public class EditionChecker extends FieldChecker { private static final Predicate FIRST_LETTER_CAPITALIZED = Pattern.compile("^[A-Z]").asPredicate(); private static final Predicate ONLY_NUMERALS_OR_LITERALS = Pattern.compile("^([0-9]+|[^0-9].+)$") @@ -23,6 +21,7 @@ public class EditionChecker implements Checker { public EditionChecker(BibDatabaseContext bibDatabaseContext) { + super(FieldName.EDITION); this.bibDatabaseContextEdition = Objects.requireNonNull(bibDatabaseContext); } @@ -37,20 +36,15 @@ public EditionChecker(BibDatabaseContext bibDatabaseContext) { * This should be an ordinal, and should have the first letter capitalized. */ @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.EDITION); - if (!value.isPresent()) { - return Collections.emptyList(); - } - + protected List checkValue(String value, BibEntry entry) { //BibLaTeX - if (bibDatabaseContextEdition.isBiblatexMode() && !ONLY_NUMERALS_OR_LITERALS.test(value.get().trim())) { + if (bibDatabaseContextEdition.isBiblatexMode() && !ONLY_NUMERALS_OR_LITERALS.test(value.trim())) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should contain an integer or a literal"), entry, FieldName.EDITION)); } //BibTeX - if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.get().trim())) { + if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should have the first letter capitalized"), entry, FieldName.EDITION)); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/FieldChecker.java b/src/main/java/net/sf/jabref/logic/integrity/FieldChecker.java new file mode 100644 index 00000000000..e1ead59ee0c --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/integrity/FieldChecker.java @@ -0,0 +1,27 @@ +package net.sf.jabref.logic.integrity; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import net.sf.jabref.model.entry.BibEntry; + +public abstract class FieldChecker implements IntegrityCheck.Checker { + protected final String field; + + public FieldChecker(String field) { + this.field = field; + } + + @Override + public List check(BibEntry entry) { + Optional value = entry.getField(field); + if (!value.isPresent()) { + return Collections.emptyList(); + } + + return checkValue(value.get(), entry); + } + + protected abstract List checkValue(String value, BibEntry entry); +} diff --git a/src/main/java/net/sf/jabref/logic/integrity/FileChecker.java b/src/main/java/net/sf/jabref/logic/integrity/FileChecker.java index dbbbb2a66e9..12f7efd1908 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/FileChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/FileChecker.java @@ -6,7 +6,6 @@ import java.util.Optional; import java.util.stream.Collectors; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.database.BibDatabaseContext; @@ -16,25 +15,22 @@ import net.sf.jabref.model.entry.ParsedFileField; import net.sf.jabref.model.metadata.FileDirectoryPreferences; -public class FileChecker implements Checker { +public class FileChecker extends FieldChecker { private final BibDatabaseContext context; private final FileDirectoryPreferences fileDirectoryPreferences; public FileChecker(BibDatabaseContext context, FileDirectoryPreferences fileDirectoryPreferences) { + super(FieldName.FILE); this.context = context; this.fileDirectoryPreferences = fileDirectoryPreferences; } - @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.FILE); - if (!value.isPresent()) { - return Collections.emptyList(); - } - List parsedFileFields = FileField.parse(value.get()).stream() + @Override + protected List checkValue(String value, BibEntry entry) { + List parsedFileFields = FileField.parse(value).stream() .filter(p -> !(p.getLink().startsWith("http://") || p.getLink().startsWith("https://"))) .collect(Collectors.toList()); diff --git a/src/main/java/net/sf/jabref/logic/integrity/HowpublishedChecker.java b/src/main/java/net/sf/jabref/logic/integrity/HowpublishedChecker.java index e9d7587129e..dd098a3b887 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/HowpublishedChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/HowpublishedChecker.java @@ -3,17 +3,15 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseContext; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class HowpublishedChecker implements Checker { +public class HowpublishedChecker extends FieldChecker { private static final Predicate FIRST_LETTER_CAPITALIZED = Pattern.compile("^[A-Z]").asPredicate(); @@ -21,6 +19,7 @@ public class HowpublishedChecker implements Checker { public HowpublishedChecker(BibDatabaseContext bibDatabaseContext) { + super(FieldName.HOWPUBLISHED); this.bibDatabaseContextEdition = Objects.requireNonNull(bibDatabaseContext); } @@ -31,14 +30,9 @@ public HowpublishedChecker(BibDatabaseContext bibDatabaseContext) { * howpublished: How something strange has been published. The first word should be capitalized. */ @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.HOWPUBLISHED); - if (!value.isPresent()) { - return Collections.emptyList(); - } - + protected List checkValue(String value, BibEntry entry) { //BibTeX - if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.get().trim())) { + if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should have the first letter capitalized"), entry, FieldName.HOWPUBLISHED)); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java index d6c7bc8d5db..8ce05ccd45f 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java @@ -3,24 +3,23 @@ import java.util.Collections; import java.util.List; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.ISBN; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class ISBNChecker implements Checker { +public class ISBNChecker extends FieldChecker { - @Override - public List check(BibEntry entry) { - if (!entry.hasField(FieldName.ISBN)) { - return Collections.emptyList(); - } + public ISBNChecker() { + super(FieldName.ISBN); + } + @Override + protected List checkValue(String value, BibEntry entry) { // Check that the ISBN is on the correct form - ISBN isbn = new ISBN(entry.getField(FieldName.ISBN).get()); + ISBN isbn = new ISBN(value); if (!isbn.isValidFormat()) { return Collections.singletonList( @@ -34,5 +33,4 @@ public List check(BibEntry entry) { return Collections.emptyList(); } - } diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java index e3976708dd0..bb90a248b3e 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java @@ -3,24 +3,22 @@ import java.util.Collections; import java.util.List; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.ISSN; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class ISSNChecker implements Checker { +public class ISSNChecker extends FieldChecker { + public ISSNChecker() { + super(FieldName.ISSN); + } @Override - public List check(BibEntry entry) { - if (!entry.hasField(FieldName.ISSN)) { - return Collections.emptyList(); - } - + protected List checkValue(String value, BibEntry entry) { // Check that the ISSN is on the correct form - String issnString = entry.getField(FieldName.ISSN).get().trim(); + String issnString = value.trim(); ISSN issn = new ISSN(issnString); if (!issn.isValidFormat()) { @@ -35,5 +33,4 @@ public List check(BibEntry entry) { .singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, FieldName.ISSN)); } } - } diff --git a/src/main/java/net/sf/jabref/logic/integrity/MonthChecker.java b/src/main/java/net/sf/jabref/logic/integrity/MonthChecker.java index 7718f7b6eb0..e72e3066ae1 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/MonthChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/MonthChecker.java @@ -3,17 +3,15 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseContext; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class MonthChecker implements Checker { +public class MonthChecker extends FieldChecker { private static final Predicate ONLY_AN_INTEGER = Pattern.compile("[1-9]|10|11|12") .asPredicate(); @@ -25,6 +23,7 @@ public class MonthChecker implements Checker { public MonthChecker(BibDatabaseContext bibDatabaseContext) { + super(FieldName.MONTH); this.bibDatabaseContextMonth = Objects.requireNonNull(bibDatabaseContext); } @@ -37,21 +36,16 @@ public MonthChecker(BibDatabaseContext bibDatabaseContext) { * Note that these abbreviations are BibTeX strings which must be given without any braces or quotes. */ @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.MONTH); - if (!value.isPresent()) { - return Collections.emptyList(); - } - + protected List checkValue(String value, BibEntry entry) { //BibLaTeX if (bibDatabaseContextMonth.isBiblatexMode() - && !(ONLY_AN_INTEGER.test(value.get().trim()) || MONTH_NORMALIZED.test(value.get().trim()))) { + && !(ONLY_AN_INTEGER.test(value.trim()) || MONTH_NORMALIZED.test(value.trim()))) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should be an integer or normalized"), entry, FieldName.MONTH)); } //BibTeX - if (!bibDatabaseContextMonth.isBiblatexMode() && !MONTH_NORMALIZED.test(value.get().trim())) { + if (!bibDatabaseContextMonth.isBiblatexMode() && !MONTH_NORMALIZED.test(value.trim())) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should be normalized"), entry, FieldName.MONTH)); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/NoteChecker.java b/src/main/java/net/sf/jabref/logic/integrity/NoteChecker.java index a278671d95c..7c2d1db594b 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/NoteChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/NoteChecker.java @@ -3,17 +3,15 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseContext; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class NoteChecker implements Checker { +public class NoteChecker extends FieldChecker { private static final Predicate FIRST_LETTER_CAPITALIZED = Pattern.compile("^[A-Z]").asPredicate(); @@ -21,6 +19,7 @@ public class NoteChecker implements Checker { public NoteChecker(BibDatabaseContext bibDatabaseContext) { + super(FieldName.NOTE); this.bibDatabaseContextEdition = Objects.requireNonNull(bibDatabaseContext); } @@ -31,14 +30,9 @@ public NoteChecker(BibDatabaseContext bibDatabaseContext) { * note: Any additional information that can help the reader. The first word should be capitalized. */ @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.NOTE); - if (!value.isPresent()) { - return Collections.emptyList(); - } - + protected List checkValue(String value, BibEntry entry) { //BibTeX - if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.get().trim())) { + if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should have the first letter capitalized"), entry, FieldName.NOTE)); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/PagesChecker.java b/src/main/java/net/sf/jabref/logic/integrity/PagesChecker.java index 92a06da6b02..1b4a712d1a0 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/PagesChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/PagesChecker.java @@ -2,11 +2,9 @@ import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; @@ -18,7 +16,7 @@ * To make it easier to maintain Scribe-compatible databases, the standard styles convert * a single dash (as in 7-33) to the double dash used in TEX to denote number ranges (as in 7--33). */ -public class PagesChecker implements Checker { +public class PagesChecker extends FieldChecker { private static final String PAGES_EXP = "" + "\\A" // begin String + "\\d+" // number @@ -33,18 +31,16 @@ public class PagesChecker implements Checker { private static final Predicate VALID_PAGE_NUMBER = Pattern.compile(PAGES_EXP).asPredicate(); + public PagesChecker() { + super(FieldName.PAGES); + } /** * Checks, if the page numbers String conforms to the BibTex manual */ @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.PAGES); - if (!value.isPresent()) { - return Collections.emptyList(); - } - - if (!VALID_PAGE_NUMBER.test(value.get().trim())) { + protected List checkValue(String value, BibEntry entry) { + if (!VALID_PAGE_NUMBER.test(value.trim())) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should contain a valid page number range"), entry, FieldName.PAGES)); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/TitleChecker.java b/src/main/java/net/sf/jabref/logic/integrity/TitleChecker.java index 49dfc4153f7..4d7a073917d 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/TitleChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/TitleChecker.java @@ -2,37 +2,33 @@ import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class TitleChecker implements Checker { +public class TitleChecker extends FieldChecker { private static final Pattern INSIDE_CURLY_BRAKETS = Pattern.compile("\\{[^}\\{]*\\}"); private static final Predicate HAS_CAPITAL_LETTERS = Pattern.compile("[\\p{Lu}\\p{Lt}]").asPredicate(); + public TitleChecker() { + super(FieldName.TITLE); + } + /** + * Algorithm: + * - remove trailing whitespaces + * - ignore first letter as this can always be written in caps + * - remove everything that is in brackets + * - check if at least one capital letter is in the title + */ @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.TITLE); - if (!value.isPresent()) { - return Collections.emptyList(); - } - - /* - * Algorithm: - * - remove trailing whitespaces - * - ignore first letter as this can always be written in caps - * - remove everything that is in brackets - * - check if at least one capital letter is in the title - */ - String valueTrimmed = value.get().trim(); + protected List checkValue(String value, BibEntry entry) { + String valueTrimmed = value.trim(); String valueIgnoringFirstLetter = valueTrimmed.startsWith("{") ? valueTrimmed : valueTrimmed.substring(1); String valueOnlySpacesWithinCurlyBraces = valueIgnoringFirstLetter; while (true) { diff --git a/src/main/java/net/sf/jabref/logic/integrity/UrlChecker.java b/src/main/java/net/sf/jabref/logic/integrity/UrlChecker.java index d0dec075d6b..2e333113dc5 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/UrlChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/UrlChecker.java @@ -2,23 +2,20 @@ import java.util.Collections; import java.util.List; -import java.util.Optional; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class UrlChecker implements Checker { +public class UrlChecker extends FieldChecker { - @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.URL); - if (!value.isPresent()) { - return Collections.emptyList(); - } + public UrlChecker() { + super(FieldName.URL); + } - if (!value.get().contains("://")) { + @Override + protected List checkValue(String value, BibEntry entry) { + if (!value.contains("://")) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should contain a protocol") + ": http[s]://, file://, ftp://, ...", entry, FieldName.URL)); diff --git a/src/main/java/net/sf/jabref/logic/integrity/YearChecker.java b/src/main/java/net/sf/jabref/logic/integrity/YearChecker.java index 1ffcf3e071c..8b68d8fa478 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/YearChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/YearChecker.java @@ -2,22 +2,23 @@ import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.FieldName; -public class YearChecker implements Checker { +public class YearChecker extends FieldChecker { private static final Predicate CONTAINS_FOUR_DIGIT = Pattern.compile("([^0-9]|^)[0-9]{4}([^0-9]|$)") .asPredicate(); private static final Predicate ENDS_WITH_FOUR_DIGIT = Pattern.compile("[0-9]{4}$").asPredicate(); private static final String PUNCTUATION_MARKS = "[(){},.;!?<>%&$]"; + public YearChecker() { + super(FieldName.YEAR); + } /** * Checks, if the number String contains a four digit year and ends with it. @@ -27,18 +28,13 @@ public class YearChecker implements Checker { * Source: http://ftp.fernuni-hagen.de/ftp-dir/pub/mirrors/www.ctan.org/biblio/bibtex/base/btxdoc.pdf */ @Override - public List check(BibEntry entry) { - Optional value = entry.getField(FieldName.YEAR); - if (!value.isPresent()) { - return Collections.emptyList(); - } - - if (!CONTAINS_FOUR_DIGIT.test(value.get().trim())) { + protected List checkValue(String value, BibEntry entry) { + if (!CONTAINS_FOUR_DIGIT.test(value.trim())) { return Collections.singletonList(new IntegrityMessage( Localization.lang("should contain a four digit number"), entry, FieldName.YEAR)); } - if (!ENDS_WITH_FOUR_DIGIT.test(value.get().replaceAll(PUNCTUATION_MARKS, ""))) { + if (!ENDS_WITH_FOUR_DIGIT.test(value.replaceAll(PUNCTUATION_MARKS, ""))) { return Collections.singletonList( new IntegrityMessage(Localization.lang("last four nonpunctuation characters should be numerals"), entry, FieldName.YEAR)); From 6f44bf2971f799522f7a509c400c34e1ff7fea0b Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 15 Jan 2017 15:26:53 +0100 Subject: [PATCH 2/2] Introduce new ValueChecker interface and use adapter to convert them to a normal Checker --- .../logic/integrity/AbbreviationChecker.java | 18 ++---- .../logic/integrity/AuthorNameChecker.java | 36 ------------ .../logic/integrity/BiblatexPagesChecker.java | 46 ---------------- .../logic/integrity/BooktitleChecker.java | 18 ++---- .../logic/integrity/BracketChecker.java | 20 ++----- .../logic/integrity/DOIValidityChecker.java | 17 ++---- .../logic/integrity/EditionChecker.java | 18 ++---- .../jabref/logic/integrity/FieldChecker.java | 12 ++-- .../jabref/logic/integrity/FieldCheckers.java | 51 +++++++++++++++++ .../jabref/logic/integrity/FileChecker.java | 13 ++--- .../logic/integrity/HowPublishedChecker.java | 37 +++++++++++++ .../logic/integrity/HowpublishedChecker.java | 42 -------------- .../jabref/logic/integrity/ISBNChecker.java | 22 ++------ .../jabref/logic/integrity/ISSNChecker.java | 21 ++----- .../logic/integrity/IntegrityCheck.java | 30 ++-------- .../jabref/logic/integrity/MonthChecker.java | 18 ++---- .../jabref/logic/integrity/NoteChecker.java | 15 ++--- .../jabref/logic/integrity/PagesChecker.java | 55 +++++++++++-------- .../logic/integrity/PersonNamesChecker.java | 19 +++++++ .../jabref/logic/integrity/TitleChecker.java | 26 +++++---- .../sf/jabref/logic/integrity/UrlChecker.java | 19 ++----- .../jabref/logic/integrity/ValueChecker.java | 11 ++++ .../jabref/logic/integrity/YearChecker.java | 22 ++------ 23 files changed, 241 insertions(+), 345 deletions(-) delete mode 100644 src/main/java/net/sf/jabref/logic/integrity/AuthorNameChecker.java delete mode 100644 src/main/java/net/sf/jabref/logic/integrity/BiblatexPagesChecker.java create mode 100644 src/main/java/net/sf/jabref/logic/integrity/FieldCheckers.java create mode 100644 src/main/java/net/sf/jabref/logic/integrity/HowPublishedChecker.java delete mode 100644 src/main/java/net/sf/jabref/logic/integrity/HowpublishedChecker.java create mode 100644 src/main/java/net/sf/jabref/logic/integrity/PersonNamesChecker.java create mode 100644 src/main/java/net/sf/jabref/logic/integrity/ValueChecker.java diff --git a/src/main/java/net/sf/jabref/logic/integrity/AbbreviationChecker.java b/src/main/java/net/sf/jabref/logic/integrity/AbbreviationChecker.java index 3de0e11f12f..914832dcbf2 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/AbbreviationChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/AbbreviationChecker.java @@ -1,25 +1,17 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -public class AbbreviationChecker extends FieldChecker { - - - public AbbreviationChecker(String field) { - super(field); - } +public class AbbreviationChecker implements ValueChecker { @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { if (value.contains(".")) { - return Collections - .singletonList(new IntegrityMessage(Localization.lang("abbreviation detected"), entry, field)); + return Optional.of(Localization.lang("abbreviation detected")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/AuthorNameChecker.java b/src/main/java/net/sf/jabref/logic/integrity/AuthorNameChecker.java deleted file mode 100644 index fa80f2c8c9c..00000000000 --- a/src/main/java/net/sf/jabref/logic/integrity/AuthorNameChecker.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.sf.jabref.logic.integrity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import net.sf.jabref.logic.integrity.IntegrityCheck.Checker; -import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldProperty; -import net.sf.jabref.model.entry.InternalBibtexFields; - -public class AuthorNameChecker implements Checker { - - @Override - public List check(BibEntry entry) { - List result = new ArrayList<>(); - for (String field : entry.getFieldNames()) { - if (InternalBibtexFields.getFieldProperties(field).contains(FieldProperty.PERSON_NAMES)) { - Optional value = entry.getField(field); - if (!value.isPresent()) { - return Collections.emptyList(); - } - - String valueTrimmedAndLowerCase = value.get().trim().toLowerCase(); - if (valueTrimmedAndLowerCase.startsWith("and ") || valueTrimmedAndLowerCase.startsWith(",")) { - result.add(new IntegrityMessage(Localization.lang("should start with a name"), entry, field)); - } else if (valueTrimmedAndLowerCase.endsWith(" and") || valueTrimmedAndLowerCase.endsWith(",")) { - result.add(new IntegrityMessage(Localization.lang("should end with a name"), entry, field)); - } - } - } - return result; - } -} diff --git a/src/main/java/net/sf/jabref/logic/integrity/BiblatexPagesChecker.java b/src/main/java/net/sf/jabref/logic/integrity/BiblatexPagesChecker.java deleted file mode 100644 index 0ceb91a177b..00000000000 --- a/src/main/java/net/sf/jabref/logic/integrity/BiblatexPagesChecker.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.sf.jabref.logic.integrity; - -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; - -/** -* Same as {@link PagesChecker} but allows single dash as well -*/ -public class BiblatexPagesChecker extends FieldChecker { - - private static final String PAGES_EXP = "" + "\\A" // begin String - + "\\d+" // number - + "(?:" // non-capture group - + "\\+|\\-{1,2}\\d+" // + or --number (range) - + ")?" // optional group - + "(?:" // non-capture group - + "," // comma - + "\\d+(?:\\+|\\-{1,2}\\d+)?" // repeat former pattern - + ")*" // repeat group 0,* - + "\\z"; // end String - - private static final Predicate VALID_PAGE_NUMBER = Pattern.compile(PAGES_EXP).asPredicate(); - - public BiblatexPagesChecker() { - super(FieldName.PAGES); - } - - /** - * Checks, if the page numbers String conforms to the BibTex manual - */ - @Override - protected List checkValue(String value, BibEntry entry) { - if (!VALID_PAGE_NUMBER.test(value.trim())) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should contain a valid page number range"), entry, FieldName.PAGES)); - } - - return Collections.emptyList(); - } -} diff --git a/src/main/java/net/sf/jabref/logic/integrity/BooktitleChecker.java b/src/main/java/net/sf/jabref/logic/integrity/BooktitleChecker.java index 0f2ba5e0747..cd8363bae5a 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/BooktitleChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/BooktitleChecker.java @@ -1,26 +1,18 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; import java.util.Locale; +import java.util.Optional; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class BooktitleChecker extends FieldChecker { - - public BooktitleChecker() { - super(FieldName.BOOKTITLE); - } +public class BooktitleChecker implements ValueChecker { @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { if (value.toLowerCase(Locale.ENGLISH).endsWith("conference on")) { - return Collections.singletonList( - new IntegrityMessage(Localization.lang("booktitle ends with 'conference on'"), entry, field)); + return Optional.of(Localization.lang("booktitle ends with 'conference on'")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/BracketChecker.java b/src/main/java/net/sf/jabref/logic/integrity/BracketChecker.java index bf7ce8d2f05..eabd71d16af 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/BracketChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/BracketChecker.java @@ -1,19 +1,13 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -public class BracketChecker extends FieldChecker { - - public BracketChecker(String field) { - super(field); - } +public class BracketChecker implements ValueChecker { @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { // metaphor: integer-based stack (push + / pop -) int counter = 0; for (char a : value.trim().toCharArray()) { @@ -21,8 +15,7 @@ protected List checkValue(String value, BibEntry entry) { counter++; } else if (a == '}') { if (counter == 0) { - return Collections.singletonList( - new IntegrityMessage(Localization.lang("unexpected closing curly bracket"), entry, field)); + return Optional.of(Localization.lang("unexpected closing curly bracket")); } else { counter--; } @@ -30,10 +23,9 @@ protected List checkValue(String value, BibEntry entry) { } if (counter > 0) { - return Collections.singletonList( - new IntegrityMessage(Localization.lang("unexpected opening curly bracket"), entry, field)); + return Optional.of(Localization.lang("unexpected opening curly bracket")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/DOIValidityChecker.java b/src/main/java/net/sf/jabref/logic/integrity/DOIValidityChecker.java index 7db74aa8746..8dbe5e5cd12 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/DOIValidityChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/DOIValidityChecker.java @@ -1,25 +1,18 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.DOI; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class DOIValidityChecker extends FieldChecker { - - public DOIValidityChecker() { - super(FieldName.DOI); - } +public class DOIValidityChecker implements ValueChecker { @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { if (DOI.isValid(value)) { - return Collections.emptyList(); + return Optional.empty(); } else { - return Collections.singletonList(new IntegrityMessage(Localization.lang("DOI %0 is invalid", value), entry, field)); + return Optional.of(Localization.lang("DOI %0 is invalid", value)); } } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/EditionChecker.java b/src/main/java/net/sf/jabref/logic/integrity/EditionChecker.java index 4c4dada35be..6651ff16dc6 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/EditionChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/EditionChecker.java @@ -1,17 +1,14 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseContext; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class EditionChecker extends FieldChecker { +public class EditionChecker implements ValueChecker { private static final Predicate FIRST_LETTER_CAPITALIZED = Pattern.compile("^[A-Z]").asPredicate(); private static final Predicate ONLY_NUMERALS_OR_LITERALS = Pattern.compile("^([0-9]+|[^0-9].+)$") @@ -21,7 +18,6 @@ public class EditionChecker extends FieldChecker { public EditionChecker(BibDatabaseContext bibDatabaseContext) { - super(FieldName.EDITION); this.bibDatabaseContextEdition = Objects.requireNonNull(bibDatabaseContext); } @@ -36,19 +32,17 @@ public EditionChecker(BibDatabaseContext bibDatabaseContext) { * This should be an ordinal, and should have the first letter capitalized. */ @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { //BibLaTeX if (bibDatabaseContextEdition.isBiblatexMode() && !ONLY_NUMERALS_OR_LITERALS.test(value.trim())) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should contain an integer or a literal"), entry, FieldName.EDITION)); + return Optional.of(Localization.lang("should contain an integer or a literal")); } //BibTeX if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should have the first letter capitalized"), entry, FieldName.EDITION)); + return Optional.of(Localization.lang("should have the first letter capitalized")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/FieldChecker.java b/src/main/java/net/sf/jabref/logic/integrity/FieldChecker.java index e1ead59ee0c..a8655a13bbc 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/FieldChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/FieldChecker.java @@ -2,15 +2,19 @@ import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; +import net.sf.jabref.logic.util.OptionalUtil; import net.sf.jabref.model.entry.BibEntry; -public abstract class FieldChecker implements IntegrityCheck.Checker { +public class FieldChecker implements IntegrityCheck.Checker { protected final String field; + private final ValueChecker checker; - public FieldChecker(String field) { + public FieldChecker(String field, ValueChecker checker) { this.field = field; + this.checker = Objects.requireNonNull(checker); } @Override @@ -20,8 +24,6 @@ public List check(BibEntry entry) { return Collections.emptyList(); } - return checkValue(value.get(), entry); + return OptionalUtil.toList(checker.checkValue(value.get()).map(message -> new IntegrityMessage(message, entry, field))); } - - protected abstract List checkValue(String value, BibEntry entry); } diff --git a/src/main/java/net/sf/jabref/logic/integrity/FieldCheckers.java b/src/main/java/net/sf/jabref/logic/integrity/FieldCheckers.java new file mode 100644 index 00000000000..f8098c95910 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/integrity/FieldCheckers.java @@ -0,0 +1,51 @@ +package net.sf.jabref.logic.integrity; + +import java.util.List; +import java.util.stream.Collectors; + +import net.sf.jabref.model.database.BibDatabaseContext; +import net.sf.jabref.model.entry.FieldName; +import net.sf.jabref.model.entry.InternalBibtexFields; +import net.sf.jabref.model.metadata.FileDirectoryPreferences; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; + +public class FieldCheckers { + static List getAll(BibDatabaseContext databaseContext, FileDirectoryPreferences fileDirectoryPreferences) { + return getAllMap(databaseContext, fileDirectoryPreferences) + .entries().stream() + .map(pair -> new FieldChecker(pair.getKey(), pair.getValue())) + .collect(Collectors.toList()); + } + + private static Multimap getAllMap(BibDatabaseContext databaseContext, FileDirectoryPreferences fileDirectoryPreferences) { + ArrayListMultimap fieldCheckers = ArrayListMultimap.create(50, 10); + + for (String field : InternalBibtexFields.getJournalNameFields()) { + fieldCheckers.put(field, new AbbreviationChecker()); + } + for (String field : InternalBibtexFields.getBookNameFields()) { + fieldCheckers.put(field, new AbbreviationChecker()); + } + for (String field : InternalBibtexFields.getPersonNameFields()) { + fieldCheckers.put(field, new PersonNamesChecker()); + } + fieldCheckers.put(FieldName.BOOKTITLE, new BooktitleChecker()); + fieldCheckers.put(FieldName.TITLE, new BracketChecker()); + fieldCheckers.put(FieldName.TITLE, new TitleChecker(databaseContext)); + fieldCheckers.put(FieldName.DOI, new DOIValidityChecker()); + fieldCheckers.put(FieldName.EDITION, new EditionChecker(databaseContext)); + fieldCheckers.put(FieldName.FILE, new FileChecker(databaseContext, fileDirectoryPreferences)); + fieldCheckers.put(FieldName.HOWPUBLISHED, new HowPublishedChecker(databaseContext)); + fieldCheckers.put(FieldName.ISBN, new ISBNChecker()); + fieldCheckers.put(FieldName.ISSN, new ISSNChecker()); + fieldCheckers.put(FieldName.MONTH, new MonthChecker(databaseContext)); + fieldCheckers.put(FieldName.NOTE, new NoteChecker(databaseContext)); + fieldCheckers.put(FieldName.PAGES, new PagesChecker(databaseContext)); + fieldCheckers.put(FieldName.URL, new UrlChecker()); + fieldCheckers.put(FieldName.YEAR, new YearChecker()); + + return fieldCheckers; + } +} diff --git a/src/main/java/net/sf/jabref/logic/integrity/FileChecker.java b/src/main/java/net/sf/jabref/logic/integrity/FileChecker.java index 12f7efd1908..21253e91011 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/FileChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/FileChecker.java @@ -1,7 +1,6 @@ package net.sf.jabref.logic.integrity; import java.io.File; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -9,27 +8,24 @@ import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.database.BibDatabaseContext; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; import net.sf.jabref.model.entry.FileField; import net.sf.jabref.model.entry.ParsedFileField; import net.sf.jabref.model.metadata.FileDirectoryPreferences; -public class FileChecker extends FieldChecker { +public class FileChecker implements ValueChecker { private final BibDatabaseContext context; private final FileDirectoryPreferences fileDirectoryPreferences; public FileChecker(BibDatabaseContext context, FileDirectoryPreferences fileDirectoryPreferences) { - super(FieldName.FILE); this.context = context; this.fileDirectoryPreferences = fileDirectoryPreferences; } @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { List parsedFileFields = FileField.parse(value).stream() .filter(p -> !(p.getLink().startsWith("http://") || p.getLink().startsWith("https://"))) .collect(Collectors.toList()); @@ -37,11 +33,10 @@ protected List checkValue(String value, BibEntry entry) { for (ParsedFileField p : parsedFileFields) { Optional file = FileUtil.expandFilename(context, p.getLink(), fileDirectoryPreferences); if ((!file.isPresent()) || !file.get().exists()) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("link should refer to a correct file path"), entry, FieldName.FILE)); + return Optional.of(Localization.lang("link should refer to a correct file path")); } } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/HowPublishedChecker.java b/src/main/java/net/sf/jabref/logic/integrity/HowPublishedChecker.java new file mode 100644 index 00000000000..2d14e6b0275 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/integrity/HowPublishedChecker.java @@ -0,0 +1,37 @@ +package net.sf.jabref.logic.integrity; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.regex.Pattern; + +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.database.BibDatabaseContext; + +public class HowPublishedChecker implements ValueChecker { + + private static final Predicate FIRST_LETTER_CAPITALIZED = Pattern.compile("^[A-Z]").asPredicate(); + + private final BibDatabaseContext databaseContext; + + + public HowPublishedChecker(BibDatabaseContext databaseContext) { + this.databaseContext = Objects.requireNonNull(databaseContext); + } + + /** + * Official BibTeX specification: + * HowPublished: How something strange has been published. The first word should be capitalized. + * BibLaTeX package documentation (Section 4.9.1): + * The BibLaTeX package will automatically capitalize the first word when required at the beginning of a sentence. + */ + @Override + public Optional checkValue(String value) { + //BibTeX + if (!databaseContext.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { + return Optional.of(Localization.lang("should have the first letter capitalized")); + } + + return Optional.empty(); + } +} diff --git a/src/main/java/net/sf/jabref/logic/integrity/HowpublishedChecker.java b/src/main/java/net/sf/jabref/logic/integrity/HowpublishedChecker.java deleted file mode 100644 index dd098a3b887..00000000000 --- a/src/main/java/net/sf/jabref/logic/integrity/HowpublishedChecker.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.sf.jabref.logic.integrity; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.database.BibDatabaseContext; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; - -public class HowpublishedChecker extends FieldChecker { - - private static final Predicate FIRST_LETTER_CAPITALIZED = Pattern.compile("^[A-Z]").asPredicate(); - - private final BibDatabaseContext bibDatabaseContextEdition; - - - public HowpublishedChecker(BibDatabaseContext bibDatabaseContext) { - super(FieldName.HOWPUBLISHED); - this.bibDatabaseContextEdition = Objects.requireNonNull(bibDatabaseContext); - } - - /** - * BibLaTeX package documentation (Section 4.9.1): - * The BibLaTeX package will automatically capitalize the first word when required at the beginning of a sentence. - * Official BibTeX specification: - * howpublished: How something strange has been published. The first word should be capitalized. - */ - @Override - protected List checkValue(String value, BibEntry entry) { - //BibTeX - if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should have the first letter capitalized"), entry, FieldName.HOWPUBLISHED)); - } - - return Collections.emptyList(); - } -} diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java index 8ce05ccd45f..226cfc49449 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java @@ -1,36 +1,26 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.ISBN; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class ISBNChecker extends FieldChecker { - - - public ISBNChecker() { - super(FieldName.ISBN); - } +public class ISBNChecker implements ValueChecker { @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { // Check that the ISBN is on the correct form ISBN isbn = new ISBN(value); if (!isbn.isValidFormat()) { - return Collections.singletonList( - new IntegrityMessage(Localization.lang("incorrect format"), entry, FieldName.ISBN)); + return Optional.of(Localization.lang("incorrect format")); } if (!isbn.isValidChecksum()) { - return Collections - .singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, FieldName.ISBN)); + return Optional.of(Localization.lang("incorrect control digit")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java index bb90a248b3e..e8a1d128140 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/ISSNChecker.java @@ -1,36 +1,27 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.util.ISSN; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class ISSNChecker extends FieldChecker { - - public ISSNChecker() { - super(FieldName.ISSN); - } +public class ISSNChecker implements ValueChecker { @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { // Check that the ISSN is on the correct form String issnString = value.trim(); ISSN issn = new ISSN(issnString); if (!issn.isValidFormat()) { - return Collections.singletonList( - new IntegrityMessage(Localization.lang("incorrect format"), entry, FieldName.ISSN)); + return Optional.of(Localization.lang("incorrect format")); } if (issn.isValidChecksum()) { - return Collections.emptyList(); + return Optional.empty(); } else { - return Collections - .singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, FieldName.ISSN)); + return Optional.of(Localization.lang("incorrect control digit")); } } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java index 7d9ae96482b..48e2861f5d3 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/net/sf/jabref/logic/integrity/IntegrityCheck.java @@ -7,8 +7,6 @@ import net.sf.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences; import net.sf.jabref.model.database.BibDatabaseContext; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -import net.sf.jabref.model.entry.InternalBibtexFields; import net.sf.jabref.model.metadata.FileDirectoryPreferences; public class IntegrityCheck { @@ -43,41 +41,21 @@ private List checkBibtexEntry(BibEntry entry) { return result; } - result.addAll(new AuthorNameChecker().check(entry)); + for (FieldChecker checker : FieldCheckers.getAll(bibDatabaseContext, fileDirectoryPreferences)) { + result.addAll(checker.check(entry)); + } - // BibTeX only checkers if (!bibDatabaseContext.isBiblatexMode()) { - result.addAll(new TitleChecker().check(entry)); - result.addAll(new PagesChecker().check(entry)); + // BibTeX only checkers result.addAll(new ASCIICharacterChecker().check(entry)); result.addAll(new NoBibtexFieldChecker().check(entry)); result.addAll(new BibTeXEntryTypeChecker().check(entry)); - } else { - result.addAll(new BiblatexPagesChecker().check(entry)); } - result.addAll(new BracketChecker(FieldName.TITLE).check(entry)); - result.addAll(new YearChecker().check(entry)); result.addAll(new BibtexkeyChecker().check(entry)); - result.addAll(new EditionChecker(bibDatabaseContext).check(entry)); - result.addAll(new NoteChecker(bibDatabaseContext).check(entry)); - result.addAll(new HowpublishedChecker(bibDatabaseContext).check(entry)); - result.addAll(new MonthChecker(bibDatabaseContext).check(entry)); - result.addAll(new UrlChecker().check(entry)); - result.addAll(new FileChecker(bibDatabaseContext, fileDirectoryPreferences).check(entry)); result.addAll(new TypeChecker().check(entry)); - for (String journalField : InternalBibtexFields.getJournalNameFields()) { - result.addAll(new AbbreviationChecker(journalField).check(entry)); - } - for (String bookNameField : InternalBibtexFields.getBookNameFields()) { - result.addAll(new AbbreviationChecker(bookNameField).check(entry)); - } result.addAll(new BibStringChecker().check(entry)); result.addAll(new HTMLCharacterChecker().check(entry)); - result.addAll(new BooktitleChecker().check(entry)); - result.addAll(new ISSNChecker().check(entry)); - result.addAll(new ISBNChecker().check(entry)); - result.addAll(new DOIValidityChecker().check(entry)); result.addAll(new EntryLinkChecker(bibDatabaseContext.getDatabase()).check(entry)); result.addAll(new BibtexkeyDeviationChecker(bibDatabaseContext, bibtexKeyPatternPreferences).check(entry)); diff --git a/src/main/java/net/sf/jabref/logic/integrity/MonthChecker.java b/src/main/java/net/sf/jabref/logic/integrity/MonthChecker.java index e72e3066ae1..0ef0ae4c404 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/MonthChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/MonthChecker.java @@ -1,17 +1,14 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseContext; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class MonthChecker extends FieldChecker { +public class MonthChecker implements ValueChecker { private static final Predicate ONLY_AN_INTEGER = Pattern.compile("[1-9]|10|11|12") .asPredicate(); @@ -23,7 +20,6 @@ public class MonthChecker extends FieldChecker { public MonthChecker(BibDatabaseContext bibDatabaseContext) { - super(FieldName.MONTH); this.bibDatabaseContextMonth = Objects.requireNonNull(bibDatabaseContext); } @@ -36,20 +32,18 @@ public MonthChecker(BibDatabaseContext bibDatabaseContext) { * Note that these abbreviations are BibTeX strings which must be given without any braces or quotes. */ @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { //BibLaTeX if (bibDatabaseContextMonth.isBiblatexMode() && !(ONLY_AN_INTEGER.test(value.trim()) || MONTH_NORMALIZED.test(value.trim()))) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should be an integer or normalized"), entry, FieldName.MONTH)); + return Optional.of(Localization.lang("should be an integer or normalized")); } //BibTeX if (!bibDatabaseContextMonth.isBiblatexMode() && !MONTH_NORMALIZED.test(value.trim())) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should be normalized"), entry, FieldName.MONTH)); + return Optional.of(Localization.lang("should be normalized")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/NoteChecker.java b/src/main/java/net/sf/jabref/logic/integrity/NoteChecker.java index 7c2d1db594b..e17b09830ac 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/NoteChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/NoteChecker.java @@ -1,17 +1,14 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabaseContext; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class NoteChecker extends FieldChecker { +public class NoteChecker implements ValueChecker { private static final Predicate FIRST_LETTER_CAPITALIZED = Pattern.compile("^[A-Z]").asPredicate(); @@ -19,7 +16,6 @@ public class NoteChecker extends FieldChecker { public NoteChecker(BibDatabaseContext bibDatabaseContext) { - super(FieldName.NOTE); this.bibDatabaseContextEdition = Objects.requireNonNull(bibDatabaseContext); } @@ -30,13 +26,12 @@ public NoteChecker(BibDatabaseContext bibDatabaseContext) { * note: Any additional information that can help the reader. The first word should be capitalized. */ @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { //BibTeX if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should have the first letter capitalized"), entry, FieldName.NOTE)); + return Optional.of(Localization.lang("should have the first letter capitalized")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/PagesChecker.java b/src/main/java/net/sf/jabref/logic/integrity/PagesChecker.java index 1b4a712d1a0..839c734496f 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/PagesChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/PagesChecker.java @@ -1,24 +1,15 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; +import net.sf.jabref.model.database.BibDatabaseContext; -/** - * From BibTex manual: - * One or more page numbers or range of numbers, such as 42--111 or 7,41,73--97 or 43+ - * (the '+' in this last example indicates pages following that don't form a simple range). - * To make it easier to maintain Scribe-compatible databases, the standard styles convert - * a single dash (as in 7-33) to the double dash used in TEX to denote number ranges (as in 7--33). - */ -public class PagesChecker extends FieldChecker { +public class PagesChecker implements ValueChecker { - private static final String PAGES_EXP = "" + "\\A" // begin String + private static final String PAGES_EXP_BIBTEX = "" + "\\A" // begin String + "\\d+" // number + "(?:" // non-capture group + "\\+|\\-{2}\\d+" // + or --number (range) @@ -29,22 +20,42 @@ public class PagesChecker extends FieldChecker { + ")*" // repeat group 0,* + "\\z"; // end String - private static final Predicate VALID_PAGE_NUMBER = Pattern.compile(PAGES_EXP).asPredicate(); + private static final String PAGES_EXP_BIBLATEX = "" + "\\A" // begin String + + "\\d+" // number + + "(?:" // non-capture group + + "\\+|\\-{1,2}\\d+" // + or --number (range) + + ")?" // optional group + + "(?:" // non-capture group + + "," // comma + + "\\d+(?:\\+|\\-{1,2}\\d+)?" // repeat former pattern + + ")*" // repeat group 0,* + + "\\z"; // end String + + private final Predicate isValidPageNumber; - public PagesChecker() { - super(FieldName.PAGES); + public PagesChecker(BibDatabaseContext databaseContext) { + if (databaseContext.isBiblatexMode()) { + isValidPageNumber = Pattern.compile(PAGES_EXP_BIBLATEX).asPredicate(); + } else { + isValidPageNumber = Pattern.compile(PAGES_EXP_BIBTEX).asPredicate(); + } } /** - * Checks, if the page numbers String conforms to the BibTex manual + * From BibTex manual: + * One or more page numbers or range of numbers, such as 42--111 or 7,41,73--97 or 43+ + * (the '+' in this last example indicates pages following that don't form a simple range). + * To make it easier to maintain Scribe-compatible databases, the standard styles convert + * a single dash (as in 7-33) to the double dash used in TEX to denote number ranges (as in 7--33). + * BibLatex: + * same as above but allows single dash as well */ @Override - protected List checkValue(String value, BibEntry entry) { - if (!VALID_PAGE_NUMBER.test(value.trim())) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should contain a valid page number range"), entry, FieldName.PAGES)); + public Optional checkValue(String value) { + if (!isValidPageNumber.test(value.trim())) { + return Optional.of(Localization.lang("should contain a valid page number range")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/PersonNamesChecker.java b/src/main/java/net/sf/jabref/logic/integrity/PersonNamesChecker.java new file mode 100644 index 00000000000..7917869d48a --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/integrity/PersonNamesChecker.java @@ -0,0 +1,19 @@ +package net.sf.jabref.logic.integrity; + +import java.util.Optional; + +import net.sf.jabref.logic.l10n.Localization; + +public class PersonNamesChecker implements ValueChecker { + + @Override + public Optional checkValue(String value) { + String valueTrimmedAndLowerCase = value.trim().toLowerCase(); + if (valueTrimmedAndLowerCase.startsWith("and ") || valueTrimmedAndLowerCase.startsWith(",")) { + return Optional.of(Localization.lang("should start with a name")); + } else if (valueTrimmedAndLowerCase.endsWith(" and") || valueTrimmedAndLowerCase.endsWith(",")) { + return Optional.of(Localization.lang("should end with a name")); + } + return Optional.empty(); + } +} diff --git a/src/main/java/net/sf/jabref/logic/integrity/TitleChecker.java b/src/main/java/net/sf/jabref/logic/integrity/TitleChecker.java index 4d7a073917d..d94c1980b90 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/TitleChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/TitleChecker.java @@ -1,22 +1,22 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; +import net.sf.jabref.model.database.BibDatabaseContext; -public class TitleChecker extends FieldChecker { +public class TitleChecker implements ValueChecker { private static final Pattern INSIDE_CURLY_BRAKETS = Pattern.compile("\\{[^}\\{]*\\}"); private static final Predicate HAS_CAPITAL_LETTERS = Pattern.compile("[\\p{Lu}\\p{Lt}]").asPredicate(); - public TitleChecker() { - super(FieldName.TITLE); + private final BibDatabaseContext databaseContext; + + public TitleChecker(BibDatabaseContext databaseContext) { + this.databaseContext = databaseContext; } /** @@ -27,7 +27,11 @@ public TitleChecker() { * - check if at least one capital letter is in the title */ @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { + if (databaseContext.isBiblatexMode()) { + return Optional.empty(); + } + String valueTrimmed = value.trim(); String valueIgnoringFirstLetter = valueTrimmed.startsWith("{") ? valueTrimmed : valueTrimmed.substring(1); String valueOnlySpacesWithinCurlyBraces = valueIgnoringFirstLetter; @@ -43,11 +47,9 @@ protected List checkValue(String value, BibEntry entry) { .test(valueOnlySpacesWithinCurlyBraces); if (hasCapitalLettersThatBibtexWillConvertToSmallerOnes) { - return Collections.singletonList( - new IntegrityMessage(Localization.lang("capital letters are not masked using curly brackets {}"), - entry, FieldName.TITLE)); + return Optional.of(Localization.lang("capital letters are not masked using curly brackets {}")); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/UrlChecker.java b/src/main/java/net/sf/jabref/logic/integrity/UrlChecker.java index 2e333113dc5..63d68ca1466 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/UrlChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/UrlChecker.java @@ -1,26 +1,17 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class UrlChecker extends FieldChecker { - - public UrlChecker() { - super(FieldName.URL); - } +public class UrlChecker implements ValueChecker { @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { if (!value.contains("://")) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should contain a protocol") + ": http[s]://, file://, ftp://, ...", entry, - FieldName.URL)); + return Optional.of(Localization.lang("should contain a protocol") + ": http[s]://, file://, ftp://, ..."); } - return Collections.emptyList(); + return Optional.empty(); } } diff --git a/src/main/java/net/sf/jabref/logic/integrity/ValueChecker.java b/src/main/java/net/sf/jabref/logic/integrity/ValueChecker.java new file mode 100644 index 00000000000..abfc13d2683 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/integrity/ValueChecker.java @@ -0,0 +1,11 @@ +package net.sf.jabref.logic.integrity; + +import java.util.Optional; + +public interface ValueChecker { + /** + * Validates the specified value. + * Returns a error massage if the validation failed. Otherwise an empty optional is returned. + */ + Optional checkValue(String value); +} diff --git a/src/main/java/net/sf/jabref/logic/integrity/YearChecker.java b/src/main/java/net/sf/jabref/logic/integrity/YearChecker.java index 8b68d8fa478..d4f1d506a90 100644 --- a/src/main/java/net/sf/jabref/logic/integrity/YearChecker.java +++ b/src/main/java/net/sf/jabref/logic/integrity/YearChecker.java @@ -1,25 +1,18 @@ package net.sf.jabref.logic.integrity; -import java.util.Collections; -import java.util.List; +import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Pattern; import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FieldName; -public class YearChecker extends FieldChecker { +public class YearChecker implements ValueChecker { private static final Predicate CONTAINS_FOUR_DIGIT = Pattern.compile("([^0-9]|^)[0-9]{4}([^0-9]|$)") .asPredicate(); private static final Predicate ENDS_WITH_FOUR_DIGIT = Pattern.compile("[0-9]{4}$").asPredicate(); private static final String PUNCTUATION_MARKS = "[(){},.;!?<>%&$]"; - public YearChecker() { - super(FieldName.YEAR); - } - /** * Checks, if the number String contains a four digit year and ends with it. * Official bibtex spec: @@ -28,18 +21,15 @@ public YearChecker() { * Source: http://ftp.fernuni-hagen.de/ftp-dir/pub/mirrors/www.ctan.org/biblio/bibtex/base/btxdoc.pdf */ @Override - protected List checkValue(String value, BibEntry entry) { + public Optional checkValue(String value) { if (!CONTAINS_FOUR_DIGIT.test(value.trim())) { - return Collections.singletonList(new IntegrityMessage( - Localization.lang("should contain a four digit number"), entry, FieldName.YEAR)); + return Optional.of(Localization.lang("should contain a four digit number")); } if (!ENDS_WITH_FOUR_DIGIT.test(value.replaceAll(PUNCTUATION_MARKS, ""))) { - return Collections.singletonList( - new IntegrityMessage(Localization.lang("last four nonpunctuation characters should be numerals"), - entry, FieldName.YEAR)); + return Optional.of(Localization.lang("last four nonpunctuation characters should be numerals")); } - return Collections.emptyList(); + return Optional.empty(); } }