diff --git a/CHANGELOG.md b/CHANGELOG.md index e54e07046cb..17a18fe325e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Fixed +- We fixed an issue where when fetching from DOI, dialog selects field data based on validity. [#12549](https://github.com/JabRef/jabref/issues/12549) - We fixed an issue where the F4 shortcut key did not work without opening the right-click context menu. [#6101](https://github.com/JabRef/jabref/pull/6101) - We fixed an issue where the file renaming dialog was not resizable and its size was too small for long file names. [#12518](https://github.com/JabRef/jabref/pull/12518) - We fixed an issue where the name of the untitled database was shown as a blank space in the right-click context menu's "Copy to" option. [#12459](https://github.com/JabRef/jabref/pull/12459) diff --git a/src/main/java/org/jabref/gui/mergeentries/FetchAndMergeEntry.java b/src/main/java/org/jabref/gui/mergeentries/FetchAndMergeEntry.java index c14e0770c15..02e780fa71d 100644 --- a/src/main/java/org/jabref/gui/mergeentries/FetchAndMergeEntry.java +++ b/src/main/java/org/jabref/gui/mergeentries/FetchAndMergeEntry.java @@ -22,6 +22,7 @@ import org.jabref.logic.importer.ImportCleanup; import org.jabref.logic.importer.WebFetcher; import org.jabref.logic.importer.WebFetchers; +import org.jabref.logic.importer.fetcher.DoiFetcher; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.BackgroundTask; import org.jabref.logic.util.TaskExecutor; @@ -110,6 +111,9 @@ private void showMergeDialog(BibEntry originalEntry, BibEntry fetchedEntry, WebF dialog.setTitle(Localization.lang("Merge entry with %0 information", fetcher.getName())); dialog.setLeftHeaderText(Localization.lang("Original entry")); dialog.setRightHeaderText(Localization.lang("Entry from %0", fetcher.getName())); + if (fetcher instanceof DoiFetcher) { + dialog.autoSelectBetterFields(); + } Optional mergedEntry = dialogService.showCustomDialogAndWait(dialog).map(EntriesMergeResult::mergedEntry); if (mergedEntry.isPresent()) { diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesDialog.java b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesDialog.java index dc485757be0..8cc8fab556d 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesDialog.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesDialog.java @@ -64,4 +64,8 @@ public void setRightHeaderText(String rightHeaderText) { public void configureDiff(ShowDiffConfig diffConfig) { threeWayMergeView.showDiff(diffConfig); } + + public void autoSelectBetterFields() { + threeWayMergeView.autoSelectBetterFields(); + } } diff --git a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/FieldRowView.java b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/FieldRowView.java index e74420f9fa4..daec4a54cc1 100644 --- a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/FieldRowView.java +++ b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/FieldRowView.java @@ -30,6 +30,10 @@ */ public class FieldRowView { private static final Logger LOGGER = LoggerFactory.getLogger(FieldRowView.class); + private static final int YEAR_LOWER = 1800; + private static final int YEAR_DIF = 10; + private static final int YEAR_UPPER_DIF = 100; + private static final String MISC = "misc"; protected final FieldRowViewModel viewModel; @@ -212,4 +216,8 @@ public boolean hasEqualLeftAndRightValues() { public String toString() { return "FieldRowView [shouldShowDiffs=" + shouldShowDiffs.get() + ", fieldNameCell=" + fieldNameCell + ", leftValueCell=" + leftValueCell + ", rightValueCell=" + rightValueCell + ", mergedValueCell=" + mergedValueCell + "]"; } + + public void autoSelectBetterValue_1() { + viewModel.autoSelectBetterValue(); + } } diff --git a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/FieldRowViewModel.java b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/FieldRowViewModel.java index 46886d9bee1..732bef6591c 100644 --- a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/FieldRowViewModel.java +++ b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/FieldRowViewModel.java @@ -1,5 +1,7 @@ package org.jabref.gui.mergeentries.newmergedialog; +import java.time.Year; + import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; @@ -19,6 +21,7 @@ import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.InternalField; +import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.EntryTypeFactory; import org.jabref.model.strings.StringUtil; @@ -37,6 +40,10 @@ public enum Selection { NONE } + private static final int YEAR_LOWER = 1800; + private static final int YEAR_DIF = 10; + private static final int YEAR_UPPER_DIF = 100; + private static final String MISC = "misc"; private final Logger LOGGER = LoggerFactory.getLogger(FieldRowViewModel.class); private final BooleanProperty isFieldsMerged = new SimpleBooleanProperty(Boolean.FALSE); @@ -282,4 +289,43 @@ public void redo() throws CannotRedoException { setRightFieldValue(mergedFields); } } + + /** + * Method for selecting the 'Better' year value. + * If the local year is out of a reasonable range (e.g., before 1800 or 100 years after current year as determined by the System Clock) or differs from the DOI year by more than 10 years, it will choose the more recent year out of the two. + */ + public void autoSelectBetterValue() { + String leftVal = getLeftFieldValue(); + String rightVal = getRightFieldValue(); + if (leftVal == null || rightVal == null) { + return; + } + leftVal = leftVal.trim(); + rightVal = rightVal.trim(); + + // Logic for auto selection based on field name + // Default is right value + if ((StandardField.YEAR) == field) { + try { + int leftYear = Integer.parseInt(leftVal); + int rightYear = Integer.parseInt(rightVal); + if (leftYear < YEAR_LOWER || leftYear > (Year.now().getValue() + YEAR_UPPER_DIF)) { + selectRightValue(); // Select right value if left year is out of range, note that work created before Year 1800 will still be correctly processed + } else if (Math.abs(leftYear - rightYear) > YEAR_DIF) { + // Select value based on a difference condition + if (leftYear > rightYear) { + selectLeftValue(); + } else { + selectRightValue(); + } + } + } catch (NumberFormatException e) { + selectRightValue(); + } + } else if ((StandardField.TYPE) == field) { + if (MISC.equalsIgnoreCase(leftVal)) { + selectRightValue(); // Select right value if left value is "misc" + } + } + } } diff --git a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/ThreeWayMergeView.java b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/ThreeWayMergeView.java index e70d8ff8807..bc10099712d 100644 --- a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/ThreeWayMergeView.java +++ b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/ThreeWayMergeView.java @@ -200,4 +200,14 @@ public BibEntry getRightEntry() { public void saveConfiguration() { toolbar.saveToolbarConfiguration(); } + + /** + * Directs to the method autoSelectBetterValue() in FieldRowViewModel.java + * Select 'Better' values for each field row in the Entry + */ + public void autoSelectBetterFields() { + for (FieldRowView row : fieldRows) { + row.autoSelectBetterValue_1(); + } + } } diff --git a/src/test/java/org/jabref/gui/mergeentries/FieldRowViewModelTest.java b/src/test/java/org/jabref/gui/mergeentries/FieldRowViewModelTest.java index 712897b3db4..f4dec772897 100644 --- a/src/test/java/org/jabref/gui/mergeentries/FieldRowViewModelTest.java +++ b/src/test/java/org/jabref/gui/mergeentries/FieldRowViewModelTest.java @@ -1,5 +1,6 @@ package org.jabref.gui.mergeentries; +import java.time.Year; import java.util.Optional; import org.jabref.gui.mergeentries.newmergedialog.FieldRowViewModel; @@ -29,6 +30,11 @@ public class FieldRowViewModelTest { BibEntry rightEntry; BibEntry extraEntry; + BibEntry extraEntry2; + BibEntry extraEntry3; + BibEntry extraEntry4; + BibEntry extraEntry5; + BibEntry extraEntry6; BibEntry mergedEntry; @@ -71,6 +77,21 @@ void setup() throws ParseException { .withField(StandardField.KEYWORDS, "b, c, a") .withField(StandardField.YEAR, "2013"); + extraEntry2 = new BibEntry(StandardEntryType.InProceedings) + .withField(StandardField.YEAR, "1750"); + + extraEntry3 = new BibEntry(StandardEntryType.InProceedings) + .withField(StandardField.YEAR, String.valueOf(Year.now().getValue() + 110)); + + extraEntry4 = new BibEntry(StandardEntryType.InProceedings) + .withField(StandardField.YEAR, "2001"); + + extraEntry5 = new BibEntry(StandardEntryType.InProceedings) + .withField(StandardField.YEAR, "2022"); + + extraEntry6 = new BibEntry(StandardEntryType.InProceedings) + .withField(StandardField.YEAR, "2011"); + mergedEntry = new BibEntry(); fieldMergerFactory = new FieldMergerFactory(bibEntryPreferences); @@ -124,6 +145,7 @@ void hasEqualLeftAndRightValuesShouldReturnTrueIfKeywordsAreEqual() { void selectLeftValueShouldBeCorrect() { var monthFieldViewModel = createViewModelForField(StandardField.MONTH); monthFieldViewModel.selectLeftValue(); + assertEquals(FieldRowViewModel.Selection.LEFT, monthFieldViewModel.getSelection()); assertEquals(Optional.of(""), Optional.ofNullable(monthFieldViewModel.getMergedFieldValue())); @@ -215,7 +237,55 @@ void unmergeFieldsShouldDoNothingIfFieldsAreNotMerged() { assertEquals(oldRightGroups, groupsField.getRightFieldValue()); } + @Test + void autoSelectBetterYearWhenMergingExistingYearOutOfBounds() { + var yearField = create2ndViewModelForField(StandardField.YEAR); + yearField.autoSelectBetterValue(); + + var yearField2 = create3rdViewModelForField(StandardField.YEAR); + yearField2.autoSelectBetterValue(); + + assertEquals(FieldRowViewModel.Selection.RIGHT, yearField.getSelection()); + assertEquals(FieldRowViewModel.Selection.RIGHT, yearField2.getSelection()); + } + + @Test + void autoSelectBetterYearWhenMergingExistingYearWithinBounds() { + var yearField = create4thViewModelForField(StandardField.YEAR); + yearField.autoSelectBetterValue(); + + var yearField2 = create5thViewModelForField(StandardField.YEAR); + yearField2.autoSelectBetterValue(); + + var yearField3 = create6thViewModelForField(StandardField.YEAR); + yearField3.autoSelectBetterValue(); + + assertEquals(FieldRowViewModel.Selection.RIGHT, yearField.getSelection()); + assertEquals(FieldRowViewModel.Selection.LEFT, yearField2.getSelection()); + assertEquals(FieldRowViewModel.Selection.LEFT, yearField3.getSelection()); + } + public FieldRowViewModel createViewModelForField(Field field) { return new FieldRowViewModel(field, leftEntry, rightEntry, mergedEntry, fieldMergerFactory); } + + public FieldRowViewModel create2ndViewModelForField(Field field) { + return new FieldRowViewModel(field, extraEntry2, extraEntry6, mergedEntry, fieldMergerFactory); + } + + public FieldRowViewModel create3rdViewModelForField(Field field) { + return new FieldRowViewModel(field, extraEntry3, extraEntry6, mergedEntry, fieldMergerFactory); + } + + public FieldRowViewModel create4thViewModelForField(Field field) { + return new FieldRowViewModel(field, extraEntry4, extraEntry, mergedEntry, fieldMergerFactory); + } + + public FieldRowViewModel create5thViewModelForField(Field field) { + return new FieldRowViewModel(field, extraEntry5, extraEntry6, mergedEntry, fieldMergerFactory); + } + + public FieldRowViewModel create6thViewModelForField(Field field) { + return new FieldRowViewModel(field, extraEntry, extraEntry5, mergedEntry, fieldMergerFactory); + } }