diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index d9b2c4ab386..00000000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "recommendations": [ - "davidanson.vscode-markdownlint", - "ltex-plus.vscode-ltex-plus" - ] -} diff --git a/.vscode/ltex.dictionary.en-US.txt b/.vscode/ltex.dictionary.en-US.txt deleted file mode 100644 index 49996eb095f..00000000000 --- a/.vscode/ltex.dictionary.en-US.txt +++ /dev/null @@ -1,7 +0,0 @@ -Checkstyle -CouchDB -JabDrive -JabRef -OpenFastTrace -OpenRewrite -Temurin diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 3ae9e077a75..00000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "java.configuration.updateBuildConfiguration": "interactive", - "java.format.settings.url": "/config/VSCode Code Style.xml", - "java.checkstyle.configuration": "${workspaceFolder}/config/checkstyle/checkstyle_reviewdog.xml", - "java.checkstyle.version": "10.21.0" -} diff --git a/src/main/java/org/jabref/logic/journals/Abbreviation.java b/src/main/java/org/jabref/logic/journals/Abbreviation.java index 8c0b166543f..db8b70d1aab 100644 --- a/src/main/java/org/jabref/logic/journals/Abbreviation.java +++ b/src/main/java/org/jabref/logic/journals/Abbreviation.java @@ -1,12 +1,19 @@ + package org.jabref.logic.journals; +import java.io.Serial; import java.io.Serializable; import java.util.Objects; +import org.apache.commons.text.similarity.LevenshteinDistance; + public class Abbreviation implements Comparable, Serializable { + @Serial private static final long serialVersionUID = 1; + private static final LevenshteinDistance LEVENSHTEIN = LevenshteinDistance.getDefaultInstance(); + private transient String name; private final String abbreviation; private transient String dotlessAbbreviation; @@ -56,13 +63,33 @@ public String getDotlessAbbreviation() { return this.dotlessAbbreviation; } + public boolean isSimilar(String otherName) { + String normalizedThis = normalize(this.name); + String normalizedOther = normalize(otherName); + + int distance = LEVENSHTEIN.apply(normalizedThis, normalizedOther); + return distance <= 2; + } + + private static String normalize(String input) { + return input.toLowerCase().replaceAll("[^a-z0-9 ]", "").trim(); + } + @Override public int compareTo(Abbreviation toCompare) { + if (isSimilar(toCompare.getName())) { + return 0; + } + int nameComparison = getName().compareTo(toCompare.getName()); if (nameComparison != 0) { return nameComparison; } + if (isSimilar(toCompare.getAbbreviation())) { + return 0; + } + int abbreviationComparison = getAbbreviation().compareTo(toCompare.getAbbreviation()); if (abbreviationComparison != 0) { return abbreviationComparison; @@ -103,7 +130,9 @@ public boolean equals(Object o) { return false; } Abbreviation that = (Abbreviation) o; - return getName().equals(that.getName()) && getAbbreviation().equals(that.getAbbreviation()) && getShortestUniqueAbbreviation().equals(that.getShortestUniqueAbbreviation()); + return Objects.equals(normalize(name), normalize(that.name)) && + Objects.equals(normalize(abbreviation), normalize(that.abbreviation)) && + Objects.equals(normalize(shortestUniqueAbbreviation), normalize(that.shortestUniqueAbbreviation)); } @Override diff --git a/src/main/java/org/jabref/logic/journals/JournalAbbreviationRepository.java b/src/main/java/org/jabref/logic/journals/JournalAbbreviationRepository.java index bfc8053d488..deb05c3d528 100644 --- a/src/main/java/org/jabref/logic/journals/JournalAbbreviationRepository.java +++ b/src/main/java/org/jabref/logic/journals/JournalAbbreviationRepository.java @@ -152,7 +152,7 @@ public void addCustomAbbreviations(Collection abbreviationsToAdd) } public Optional getNextAbbreviation(String text) { - return get(text).map(abbreviation -> abbreviation.getNext(text)); + return get(text).map(abbreviation -> abbreviation.getNext(text.trim())); } public Optional getDefaultAbbreviation(String text) { diff --git a/src/test/java/org/jabref/logic/journals/AbbreviationTest.java b/src/test/java/org/jabref/logic/journals/AbbreviationTest.java index 1cd3bb5b4e1..eb603ac9c1d 100644 --- a/src/test/java/org/jabref/logic/journals/AbbreviationTest.java +++ b/src/test/java/org/jabref/logic/journals/AbbreviationTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class AbbreviationTest { @@ -111,10 +112,46 @@ void equals() { assertNotEquals("String", abbreviation); } + @Test + void testSlightDifferences() { + assertTrue(new Abbreviation("Long Name", "L. N.").isSimilar("Longn Name")); + } + + @Test + void testMissingLetter() { + assertTrue(new Abbreviation("Long Name", "L. N.").isSimilar("Long ame")); + } + + @Test + void testPunctuationDifferences() { + assertTrue(new Abbreviation("Long Name", "L. N.").isSimilar("Long, Name")); + } + + @Test + void testCaseDifferences() { + assertTrue(new Abbreviation("Long Name", "L. N.").isSimilar("LONG NAME")); + } + @Test void equalAbbrevationsWithFourComponentsAreAlsoCompareZero() { Abbreviation abbreviation1 = new Abbreviation("Long Name", "L. N.", "LN"); Abbreviation abbreviation2 = new Abbreviation("Long Name", "L. N.", "LN"); assertEquals(0, abbreviation1.compareTo(abbreviation2)); } + + @Test + void testCompareToWithFuzzyMatching() { + Abbreviation abbreviation1 = new Abbreviation("Long Name", "L. N."); + Abbreviation abbreviation2 = new Abbreviation("Long Name", "L. N."); + assertEquals(0, abbreviation1.compareTo(abbreviation2)); + + abbreviation2 = new Abbreviation("Long Name", "L. N. "); + assertEquals(0, abbreviation1.compareTo(abbreviation2)); + + abbreviation2 = new Abbreviation("Long Name", "L. N"); + assertEquals(0, abbreviation1.compareTo(abbreviation2)); + + abbreviation2 = new Abbreviation("Short Name", "S. N."); + assertNotEquals(0, abbreviation1.compareTo(abbreviation2)); + } }