Skip to content
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 @@ -125,6 +125,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- We fixed an issue where "Copy to" was enabled even if no other library was opened. [#13280](https://github.com/JabRef/jabref/pull/13280)
- We fixed an issue where the groups were still displayed after closing all libraries. [#13382](https://github.com/JabRef/jabref/issues/13382)
- Enhanced field selection logic in the Merge Entries dialog when fetching from DOI to prefer valid years and entry types. [#12549](https://github.com/JabRef/jabref/issues/12549)
- We fixed an issue where opening the Three Way Merge dialog would throw an exception when year field contains an invalid year value. [#13673](https://github.com/JabRef/jabref/issues/13673)
- We improved consistency in the Add Buttons. [#13791](https://github.com/JabRef/jabref/pull/13791)
- We fixed an issue where theme or font size are not respected for all dialogs [#13558](https://github.com/JabRef/jabref/issues/13558)
- We removed unnecessary spacing and margin in the AutomaticFieldEditor. [#13792](https://github.com/JabRef/jabref/pull/13792)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,23 @@ void newYearShouldBeSelectedForYearsWithLargeValueGap() {
}

@Test
void yearInRangeShouldBeSelected() {
void selectRightYearWhenInRange() {
BibEntry leftEntry = new BibEntry().withField(StandardField.YEAR, "1700");
BibEntry rightEntry = new BibEntry().withField(StandardField.YEAR, "2000");
FieldRowViewModel yearField = new FieldRowViewModel(StandardField.YEAR, leftEntry, rightEntry, mergedEntry, fieldMergerFactory);
yearField.autoSelectBetterValue();
assertEquals(FieldRowViewModel.Selection.RIGHT, yearField.getSelection());
}

@Test
void selectLeftYearWhenInRange() {
BibEntry leftEntry = new BibEntry().withField(StandardField.YEAR, "2005");
BibEntry rightEntry = new BibEntry().withField(StandardField.YEAR, "1700");
FieldRowViewModel yearField = new FieldRowViewModel(StandardField.YEAR, leftEntry, rightEntry, mergedEntry, fieldMergerFactory);
yearField.autoSelectBetterValue();
assertEquals(FieldRowViewModel.Selection.LEFT, yearField.getSelection());
}

public FieldRowViewModel createViewModelForField(Field field) {
return new FieldRowViewModel(field, leftEntry, rightEntry, mergedEntry, fieldMergerFactory);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.regex.Pattern;

import org.jabref.logic.integrity.YearChecker;
import org.jabref.model.strings.StringUtil;

public class YearFieldValuePlausibilityComparator extends FieldValuePlausibilityComparator {

Expand All @@ -21,28 +22,50 @@ public class YearFieldValuePlausibilityComparator extends FieldValuePlausibility

@Override
public ComparisonResult compare(String leftValue, String rightValue) {
YearChecker checker = new YearChecker();
boolean isLeftBlank = StringUtil.isBlank(leftValue);
boolean isRightBlank = StringUtil.isBlank(rightValue);
if (isLeftBlank && !isRightBlank) {
return ComparisonResult.RIGHT_BETTER;
} else if (isRightBlank && !isLeftBlank) {
return ComparisonResult.LEFT_BETTER;
} else if (isLeftBlank && isRightBlank) {
return ComparisonResult.UNDETERMINED;
}

boolean leftValid = checker.checkValue(leftValue).isEmpty();
// left and right values are not blank.

if (leftValid) {
Optional<Integer> leftYear = extractYear(leftValue);
Optional<Integer> rightYear = extractYear(rightValue);
boolean leftValueCorrectlyFormatted = YearChecker.isValueCorrectlyFormatted(leftValue);
boolean rightValueCorrectlyFormatted = YearChecker.isValueCorrectlyFormatted(rightValue);
if (leftValueCorrectlyFormatted && !rightValueCorrectlyFormatted) {
return ComparisonResult.LEFT_BETTER;
} else if (rightValueCorrectlyFormatted && !leftValueCorrectlyFormatted) {
return ComparisonResult.RIGHT_BETTER;
} else if (!leftValueCorrectlyFormatted && !rightValueCorrectlyFormatted) {
return ComparisonResult.UNDETERMINED;
}

boolean leftYearInRange = (leftYear.get() >= 1800) && (leftYear.get() <= Year.now().getValue() + 2);
// left and right values are correctly formatted.

if (leftYearInRange) {
int diff = Math.abs(leftYear.get() - rightYear.get());
if (diff > 10) {
return rightYear.get() > leftYear.get()
? ComparisonResult.RIGHT_BETTER
: ComparisonResult.LEFT_BETTER;
}
return ComparisonResult.UNDETERMINED; // years are close, undetermined
}
int leftYear = extractYear(leftValue).get();
int rightYear = extractYear(rightValue).get();
boolean leftYearInRange = (leftYear >= 1800) && (leftYear <= Year.now().getValue() + 2);
boolean rightYearInRange = (rightYear >= 1800) && (rightYear <= Year.now().getValue() + 2);
if (leftYearInRange && !rightYearInRange) {
return ComparisonResult.LEFT_BETTER;
} else if (rightYearInRange && !leftYearInRange) {
return ComparisonResult.RIGHT_BETTER;
}
return ComparisonResult.RIGHT_BETTER;
} else if (!leftYearInRange && !rightYearInRange) {
return ComparisonResult.UNDETERMINED;
}

int diff = Math.abs(leftYear - rightYear);
if (diff > 10) {
return rightYear > leftYear
? ComparisonResult.RIGHT_BETTER
: ComparisonResult.LEFT_BETTER;
}

return ComparisonResult.UNDETERMINED; // years are close, undetermined
}

/**
Expand Down
15 changes: 13 additions & 2 deletions jablib/src/main/java/org/jabref/logic/integrity/YearChecker.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

public class YearChecker implements ValueChecker {

private static final Predicate<String> CONTAINS_FOUR_DIGIT = Pattern.compile("([^0-9]|^)[0-9]{4}([^0-9]|$)")
.asPredicate();
private static final Predicate<String> CONTAINS_FOUR_DIGIT = Pattern.compile("([^0-9]|^)[0-9]{4}([^0-9]|$)").asPredicate();
private static final Predicate<String> ENDS_WITH_FOUR_DIGIT = Pattern.compile("[0-9]{4}$").asPredicate();
private static final String PUNCTUATION_MARKS = "[(){},.;!?<>%&$]";

Expand All @@ -37,4 +36,16 @@ public Optional<String> checkValue(String value) {

return Optional.empty();
}

public static boolean isValueCorrectlyFormatted(String value) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method duplicates logic from checkValue() which violates DRY principle. Should refactor to reuse existing validation logic to prevent maintenance issues.

if (StringUtil.isBlank(value)) {
return false;
}

if (!CONTAINS_FOUR_DIGIT.test(value.trim())) {
return false;
}

return ENDS_WITH_FOUR_DIGIT.test(value.replaceAll(PUNCTUATION_MARKS, ""));
}
}
Loading