Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ISBN integrity checker #1586

Merged
merged 2 commits into from
Jul 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
### Changed
- [#1026](https://github.com/JabRef/jabref/issues/1026) JabRef does no longer delete user comments outside of BibTeX entries and strings
- [#1249](https://github.com/JabRef/jabref/issues/1249) Date layout formatter added
- Added ISBN integrity checker

### Fixed
- Fixed [#1264](https://github.com/JabRef/jabref/issues/1264): S with caron does not render correctly
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/net/sf/jabref/logic/integrity/ISBNChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.sf.jabref.logic.integrity;

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;


public class ISBNChecker implements Checker {


@Override
public List<IntegrityMessage> check(BibEntry entry) {
if (!entry.hasField("isbn")) {
return Collections.emptyList();
}

// Check that the ISBN is on the correct form
ISBN isbn = new ISBN(entry.getFieldOptional("isbn").get());

if (!isbn.isValidFormat()) {
return Collections.singletonList(
new IntegrityMessage(Localization.lang("incorrect format"), entry, "isbn"));
}

if (!isbn.isValidChecksum()) {
return Collections
.singletonList(new IntegrityMessage(Localization.lang("incorrect control digit"), entry, "isbn"));
}

return Collections.emptyList();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ private List<IntegrityMessage> checkBibtexEntry(BibEntry 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));

return result;
}
Expand Down
76 changes: 76 additions & 0 deletions src/main/java/net/sf/jabref/logic/util/ISBN.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package net.sf.jabref.logic.util;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ISBN {

private static final Pattern ISBN_PATTERN = Pattern.compile("^(\\d{9}[\\dxX]|\\d{13})$");

private final String isbnString;


public ISBN(String isbnString) {
this.isbnString = Objects.requireNonNull(isbnString).trim().replace("-", "");
}

public boolean isValidFormat() {
Matcher isbnMatcher = ISBN_PATTERN.matcher(isbnString);
if (isbnMatcher.matches()) {
return true;
}
return false;
}

public boolean isValidChecksum() {
boolean valid;
if (isbnString.length() == 10) {
valid = isbn10check();
} else {
// length is either 10 or 13 based on regexp so will be 13 here
valid = isbn13check();
}
return valid;
}

public boolean isIsbn10() {
return isbn10check();
}

public boolean isIsbn13() {
return isbn13check();
}

// Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Book_Number#Check_digits
private boolean isbn10check() {
if ((isbnString == null) || (isbnString.length() != 10)) {
return false;
}

int sum = 0;
for (int pos = 0; pos <= 8; pos++) {
sum += (isbnString.charAt(pos) - '0') * ((10 - pos));
}
char control = isbnString.charAt(9);
if ((control == 'x') || (control == 'X')) {
control = '9' + 1;
}
sum += (control - '0');
return (sum % 11) == 0;
}

// Check that the control digit is correct, see e.g. https://en.wikipedia.org/wiki/International_Standard_Book_Number#Check_digits
private boolean isbn13check() {
if ((isbnString == null) || (isbnString.length() != 13)) {
return false;
}

int sum = 0;
for (int pos = 0; pos <= 12; pos++) {
sum += (isbnString.charAt(pos) - '0') * ((pos % 2) == 0 ? 1 : 3);
}
return (sum % 10) == 0;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,23 @@ public void testHTMLCharacterChecks() {

@Test
public void testISSNChecks() {
assertCorrect(createContext("issn", "0020-7217"));
assertCorrect(createContext("issn", "0020-7217"));
assertCorrect(createContext("issn", "1687-6180"));
assertCorrect(createContext("issn", "2434-561x"));
assertWrong(createContext("issn", "Some other stuff"));
assertWrong(createContext("issn", "0020-7218"));
}

@Test
public void testISBNChecks() {
assertCorrect(createContext("isbn", "0-201-53082-1"));
assertCorrect(createContext("isbn", "0-9752298-0-X"));
assertCorrect(createContext("isbn", "978-0-306-40615-7"));
assertWrong(createContext("isbn", "Some other stuff"));
assertWrong(createContext("isbn", "0-201-53082-2"));
assertWrong(createContext("isbn", "978-0-306-40615-8"));
}

private BibDatabaseContext createContext(String field, String value, String type) {
BibEntry entry = new BibEntry();
entry.setField(field, value);
Expand Down