From 93a9a8db028c780ac85bc406bb760b0e3066a392 Mon Sep 17 00:00:00 2001 From: Boji Zhang Date: Sun, 20 Oct 2024 17:13:16 +1100 Subject: [PATCH] Refactor FetchAndMergeEntry to MergingIdBasedFetcher in logic layer - Create IdBasedFetcherFactory.java - Move class from gui to org.jabref.logic.importer.fetcher - Extract WebFetchers.getIdBasedFetcherForField as parameter for flexibility - Replace DialogService with NotificationService to improve UX - Rename class to MergingIdBasedFetcher for clarity - Update all usages of FetchAndMergeEntry --- .../jabref/gui/entryeditor/EntryEditor.java | 4 +- .../gui/fieldeditors/ISSNEditorViewModel.java | 4 +- .../DoiIdentifierEditorViewModel.java | 4 +- .../ISBNIdentifierEditorViewModel.java | 4 +- .../MergeWithFetchedEntryAction.java | 7 +- .../MultiEntryMergeWithFetchedDataAction.java | 7 +- .../fetcher/IdBasedFetcherFactory.java | 11 + .../fetcher/MergingIdBasedFetcher.java} | 223 +++++++----------- 8 files changed, 112 insertions(+), 152 deletions(-) create mode 100644 src/main/java/org/jabref/logic/importer/fetcher/IdBasedFetcherFactory.java rename src/main/java/org/jabref/{gui/mergeentries/FetchAndMergeEntry.java => logic/importer/fetcher/MergingIdBasedFetcher.java} (60%) diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 6a382a7a59e1..4e6b8e25996d 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -41,7 +41,6 @@ import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.keyboard.KeyBindingRepository; import org.jabref.gui.menus.ChangeEntryTypeMenu; -import org.jabref.gui.mergeentries.FetchAndMergeEntry; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.undo.CountingUndoManager; @@ -53,6 +52,7 @@ import org.jabref.logic.help.HelpFile; import org.jabref.logic.importer.EntryBasedFetcher; import org.jabref.logic.importer.WebFetchers; +import org.jabref.logic.importer.fetcher.MergingIdBasedFetcher; import org.jabref.logic.importer.fileformat.PdfMergeMetadataImporter; import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.util.BuildInfo; @@ -450,7 +450,7 @@ private void setupToolBar() { } private void fetchAndMerge(EntryBasedFetcher fetcher) { - new FetchAndMergeEntry(libraryTab.getBibDatabaseContext(), taskExecutor, preferences, dialogService, undoManager).fetchAndMerge(currentlyEditedEntry, fetcher); + new MergingIdBasedFetcher(libraryTab.getBibDatabaseContext(), taskExecutor, preferences, dialogService, undoManager).fetchAndMerge(currentlyEditedEntry, fetcher); } public void setFocusToField(Field field) { diff --git a/src/main/java/org/jabref/gui/fieldeditors/ISSNEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/ISSNEditorViewModel.java index b260019f2f94..c16e8a1fd15f 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/ISSNEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/ISSNEditorViewModel.java @@ -7,8 +7,8 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProvider; -import org.jabref.gui.mergeentries.FetchAndMergeEntry; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.importer.fetcher.MergingIdBasedFetcher; import org.jabref.logic.integrity.FieldCheckers; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.TaskExecutor; @@ -46,7 +46,7 @@ public void showJournalInfo(Button journalInfoButton) { public void fetchBibliographyInformation(BibEntry bibEntry) { stateManager.getActiveDatabase().ifPresentOrElse( - databaseContext -> new FetchAndMergeEntry(databaseContext, taskExecutor, preferences, dialogService, undoManager) + databaseContext -> new MergingIdBasedFetcher(databaseContext, taskExecutor, preferences, dialogService, undoManager) .fetchAndMerge(bibEntry, StandardField.ISSN), () -> dialogService.notify(Localization.lang("No library selected")) ); diff --git a/src/main/java/org/jabref/gui/fieldeditors/identifier/DoiIdentifierEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/identifier/DoiIdentifierEditorViewModel.java index 7b86f1f2966e..a4a4de793456 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/identifier/DoiIdentifierEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/identifier/DoiIdentifierEditorViewModel.java @@ -6,9 +6,9 @@ import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProvider; import org.jabref.gui.desktop.os.NativeDesktop; -import org.jabref.gui.mergeentries.FetchAndMergeEntry; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.logic.importer.fetcher.CrossRef; +import org.jabref.logic.importer.fetcher.MergingIdBasedFetcher; import org.jabref.logic.integrity.FieldCheckers; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.BackgroundTask; @@ -58,7 +58,7 @@ public void lookupIdentifier(BibEntry bibEntry) { @Override public void fetchBibliographyInformation(BibEntry bibEntry) { stateManager.getActiveDatabase().ifPresentOrElse( - databaseContext -> new FetchAndMergeEntry(databaseContext, taskExecutor, preferences, dialogService, undoManager) + databaseContext -> new MergingIdBasedFetcher(databaseContext, taskExecutor, preferences, dialogService, undoManager) .fetchAndMerge(entry, field), () -> dialogService.notify(Localization.lang("No library selected")) ); diff --git a/src/main/java/org/jabref/gui/fieldeditors/identifier/ISBNIdentifierEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/identifier/ISBNIdentifierEditorViewModel.java index 99daab73f22d..3c9f02ba1416 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/identifier/ISBNIdentifierEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/identifier/ISBNIdentifierEditorViewModel.java @@ -5,8 +5,8 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProvider; -import org.jabref.gui.mergeentries.FetchAndMergeEntry; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.importer.fetcher.MergingIdBasedFetcher; import org.jabref.logic.integrity.FieldCheckers; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.TaskExecutor; @@ -34,7 +34,7 @@ public ISBNIdentifierEditorViewModel(SuggestionProvider suggestionProvider, @Override public void fetchBibliographyInformation(BibEntry bibEntry) { stateManager.getActiveDatabase().ifPresentOrElse( - databaseContext -> new FetchAndMergeEntry(databaseContext, taskExecutor, preferences, dialogService, undoManager) + databaseContext -> new MergingIdBasedFetcher(databaseContext, taskExecutor, preferences, dialogService, undoManager) .fetchAndMerge(entry, field), () -> dialogService.notify(Localization.lang("No library selected")) ); diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java index a6d8d65a4067..90027591a7f9 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java @@ -7,6 +7,7 @@ import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.importer.fetcher.MergingIdBasedFetcher; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.entry.BibEntry; @@ -33,7 +34,7 @@ public MergeWithFetchedEntryAction(DialogService dialogService, this.undoManager = undoManager; this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager) - .and(ActionHelper.isAnyFieldSetForSelectedEntry(FetchAndMergeEntry.SUPPORTED_IDENTIFIER_FIELDS, stateManager))); + .and(ActionHelper.isAnyFieldSetForSelectedEntry(MergingIdBasedFetcher.SUPPORTED_IDENTIFIER_FIELDS, stateManager))); } @Override @@ -49,7 +50,7 @@ public void execute() { } BibEntry originalEntry = stateManager.getSelectedEntries().getFirst(); - FetchAndMergeEntry fetchAndMergeEntry = new FetchAndMergeEntry( + MergingIdBasedFetcher mergingIdBasedFetcher = new MergingIdBasedFetcher( stateManager.getActiveDatabase().get(), taskExecutor, preferences, @@ -57,6 +58,6 @@ public void execute() { undoManager ); - fetchAndMergeEntry.fetchAndMerge(originalEntry); + mergingIdBasedFetcher.fetchAndMerge(originalEntry); } } diff --git a/src/main/java/org/jabref/gui/mergeentries/MultiEntryMergeWithFetchedDataAction.java b/src/main/java/org/jabref/gui/mergeentries/MultiEntryMergeWithFetchedDataAction.java index 1d842ba7763a..497283556292 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MultiEntryMergeWithFetchedDataAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MultiEntryMergeWithFetchedDataAction.java @@ -11,6 +11,7 @@ import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.importer.fetcher.MergingIdBasedFetcher; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -65,10 +66,10 @@ public void execute() { return; } - // Create an instance of FetchAndMergeEntry to perform the batch fetch and merge operation + // Create an instance of MergingIdBasedFetcher to perform the batch fetch and merge operation BibDatabaseContext bibDatabaseContext = libraryTab.getBibDatabaseContext(); - FetchAndMergeEntry fetchAndMergeEntry = new FetchAndMergeEntry(bibDatabaseContext, taskExecutor, preferences, dialogService, undoManager); + MergingIdBasedFetcher mergingIdBasedFetcher = new MergingIdBasedFetcher(bibDatabaseContext, taskExecutor, preferences, dialogService, undoManager); - fetchAndMergeEntry.fetchAndMergeBatch(selectedEntries); + mergingIdBasedFetcher.fetchAndMergeBatch(selectedEntries); } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/IdBasedFetcherFactory.java b/src/main/java/org/jabref/logic/importer/fetcher/IdBasedFetcherFactory.java new file mode 100644 index 000000000000..ae6664b5184a --- /dev/null +++ b/src/main/java/org/jabref/logic/importer/fetcher/IdBasedFetcherFactory.java @@ -0,0 +1,11 @@ +package org.jabref.logic.importer.fetcher; + +import java.util.Optional; + +import org.jabref.logic.importer.IdBasedFetcher; +import org.jabref.model.entry.field.Field; + +@FunctionalInterface +public interface IdBasedFetcherFactory { + Optional getFetcherForField(Field field); +} diff --git a/src/main/java/org/jabref/gui/mergeentries/FetchAndMergeEntry.java b/src/main/java/org/jabref/logic/importer/fetcher/MergingIdBasedFetcher.java similarity index 60% rename from src/main/java/org/jabref/gui/mergeentries/FetchAndMergeEntry.java rename to src/main/java/org/jabref/logic/importer/fetcher/MergingIdBasedFetcher.java index e1fe383b26c8..6c02409d1253 100644 --- a/src/main/java/org/jabref/gui/mergeentries/FetchAndMergeEntry.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MergingIdBasedFetcher.java @@ -1,5 +1,5 @@ -package org.jabref.gui.mergeentries; +package org.jabref.logic.importer.fetcher; import java.util.Arrays; import java.util.Comparator; @@ -11,7 +11,6 @@ import javax.swing.undo.UndoManager; -import org.jabref.gui.DialogService; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableChangeType; @@ -21,10 +20,10 @@ import org.jabref.logic.importer.FetcherServerException; import org.jabref.logic.importer.IdBasedFetcher; import org.jabref.logic.importer.ImportCleanup; -import org.jabref.logic.importer.WebFetcher; import org.jabref.logic.importer.WebFetchers; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.BackgroundTask; +import org.jabref.logic.util.NotificationService; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -39,76 +38,65 @@ /** * Class for fetching and merging bibliographic information */ -public class FetchAndMergeEntry { +public class MergingIdBasedFetcher { public static final List SUPPORTED_IDENTIFIER_FIELDS = Arrays.asList(StandardField.DOI, StandardField.EPRINT, StandardField.ISBN); - private static final Logger LOGGER = LoggerFactory.getLogger(FetchAndMergeEntry.class); - private final DialogService dialogService; + private static final Logger LOGGER = LoggerFactory.getLogger(MergingIdBasedFetcher.class); + private final NotificationService notificationService; private final UndoManager undoManager; private final BibDatabaseContext bibDatabaseContext; private final TaskExecutor taskExecutor; private final GuiPreferences preferences; - public FetchAndMergeEntry(BibDatabaseContext bibDatabaseContext, - TaskExecutor taskExecutor, - GuiPreferences preferences, - DialogService dialogService, - UndoManager undoManager) { + public MergingIdBasedFetcher(BibDatabaseContext bibDatabaseContext, + TaskExecutor taskExecutor, + GuiPreferences preferences, + NotificationService notificationService, + UndoManager undoManager) { this.bibDatabaseContext = bibDatabaseContext; this.taskExecutor = taskExecutor; this.preferences = preferences; - this.dialogService = dialogService; + this.notificationService = notificationService; this.undoManager = undoManager; } public void fetchAndMerge(BibEntry entry) { - fetchAndMerge(entry, SUPPORTED_IDENTIFIER_FIELDS); + fetchAndMerge(entry, SUPPORTED_IDENTIFIER_FIELDS, + field -> WebFetchers.getIdBasedFetcherForField(field, preferences.getImportFormatPreferences())); } public void fetchAndMerge(BibEntry entry, Field field) { - fetchAndMerge(entry, List.of(field)); + fetchAndMerge(entry, List.of(field), + f -> WebFetchers.getIdBasedFetcherForField(f, preferences.getImportFormatPreferences())); } - public void fetchAndMerge(BibEntry entry, List fields) { - fields.forEach(field -> fetchAndMergeEntryWithDialog(entry, field)); + public void fetchAndMerge(BibEntry entry, List fields, IdBasedFetcherFactory fetcherFactory) { + fields.forEach(field -> fetchAndMergeEntryWithNotification(entry, field, fetcherFactory)); } - private void fetchAndMergeEntryWithDialog(BibEntry entry, Field field) { - entry.getField(field) - .flatMap(fieldContent -> WebFetchers.getIdBasedFetcherForField(field, preferences.getImportFormatPreferences())) - .ifPresent(fetcher -> executeFetchTaskWithDialog(fetcher, field, entry)); - } - - private void executeFetchTaskWithDialog(IdBasedFetcher fetcher, Field field, BibEntry entry) { - entry.getField(field) - .ifPresent(fieldContent -> - BackgroundTask.wrap(() -> fetcher.performSearchById(fieldContent)) - .onSuccess(fetchedEntry -> processFetchedEntryWithDialog(fetchedEntry, field, entry, fetcher)) - .onFailure(exception -> handleFetchException(exception, fetcher)) - .executeWith(taskExecutor) - ); - } - - private void processFetchedEntryWithDialog(Optional fetchedEntry, Field field, BibEntry originalEntry, IdBasedFetcher fetcher) { - ImportCleanup cleanup = ImportCleanup.targeting(bibDatabaseContext.getMode(), preferences.getFieldPreferences()); - fetchedEntry.ifPresentOrElse( - entry -> { - cleanup.doPostCleanup(entry); - showMergeDialog(originalEntry, entry, fetcher); - }, - () -> dialogService.notify(Localization.lang("Cannot get info based on given %0: %1", field.getDisplayName(), originalEntry.getField(field).orElse(""))) - ); + public void fetchAndMerge(BibEntry entry, EntryBasedFetcher fetcher) { + BackgroundTask.wrap(() -> fetcher.performSearch(entry).stream().findFirst()) + .onSuccess(fetchedEntry -> fetchedEntry + .map(fe -> { + ImportCleanup cleanup = ImportCleanup.targeting(bibDatabaseContext.getMode(), preferences.getFieldPreferences()); + cleanup.doPostCleanup(fe); + return fe; + }) + .ifPresentOrElse( + fe -> mergeWithoutDialog(entry, fe), + () -> notificationService.notify(Localization.lang("Could not find any bibliographic information.")) + )) + .onFailure(exception -> { + LOGGER.error("Error while fetching entry with {} ", fetcher.getName(), exception); + notificationService.notify(Localization.lang("Error while fetching from %0: %1", fetcher.getName(), exception.getMessage())); + }) + .executeWith(taskExecutor); } - public void fetchAndMergeBatch(List entries) { - entries.forEach(entry -> SUPPORTED_IDENTIFIER_FIELDS.forEach(field -> fetchAndMergeEntry(entry, field))); - } - - private void fetchAndMergeEntry(BibEntry entry, Field field) { - entry.getField(field) - .flatMap(fieldContent -> WebFetchers.getIdBasedFetcherForField(field, preferences.getImportFormatPreferences())) - .ifPresent(fetcher -> executeFetchTask(fetcher, field, entry)); + private void fetchAndMergeEntryWithNotification(BibEntry entry, Field field, IdBasedFetcherFactory fetcherFactory) { + fetcherFactory.getFetcherForField(field) + .ifPresent(fetcher -> executeFetchTask(fetcher, field, entry)); } private void executeFetchTask(IdBasedFetcher fetcher, Field field, BibEntry entry) { @@ -119,39 +107,14 @@ private void executeFetchTask(IdBasedFetcher fetcher, Field field, BibEntry entr .executeWith(taskExecutor)); } - private void processFetchedEntry(Optional fetchedEntry, Field field, BibEntry originalEntry) { - ImportCleanup cleanup = ImportCleanup.targeting(bibDatabaseContext.getMode(), preferences.getFieldPreferences()); - fetchedEntry.ifPresentOrElse( - entry -> { - cleanup.doPostCleanup(entry); - mergeWithoutDialog(originalEntry, entry); - }, - // Notify if no entry was fetched - () -> dialogService.notify(Localization.lang("Cannot get info based on given %0: %1", field.getDisplayName(), originalEntry.getField(field).orElse(""))) - ); - } - - private void handleFetchException(Exception exception, IdBasedFetcher fetcher) { - LOGGER.error("Error while fetching bibliographic information", exception); - String fetcherName = fetcher.getName(); - // Handle different types of exceptions with specific error messages - if (exception instanceof FetcherClientException) { - dialogService.showInformationDialogAndWait(Localization.lang("Fetching information using %0", fetcherName), Localization.lang("No data was found for the identifier")); - } else if (exception instanceof FetcherServerException) { - dialogService.showInformationDialogAndWait(Localization.lang("Fetching information using %0", fetcherName), Localization.lang("Server not available")); - } else { - dialogService.showInformationDialogAndWait(Localization.lang("Fetching information using %0", fetcherName), Localization.lang("Error occurred %0", exception.getMessage())); - } + public void fetchAndMergeBatch(List entries) { + entries.forEach(entry -> SUPPORTED_IDENTIFIER_FIELDS.forEach(field -> fetchAndMergeEntry(entry, field))); } - private void mergeWithoutDialog(BibEntry originalEntry, BibEntry fetchedEntry) { - NamedCompound ce = new NamedCompound(Localization.lang("Merge entry without user interaction")); - - updateEntryTypeIfDifferent(originalEntry, fetchedEntry, ce); - updateFieldsWithNewInfo(originalEntry, fetchedEntry, ce); - removeObsoleteFields(originalEntry, fetchedEntry, ce); - - finalizeMerge(ce, originalEntry); + private void fetchAndMergeEntry(BibEntry entry, Field field) { + entry.getField(field) + .flatMap(fieldContent -> WebFetchers.getIdBasedFetcherForField(field, preferences.getImportFormatPreferences())) + .ifPresent(fetcher -> executeFetchTask(fetcher, field, entry)); } private void updateFieldsWithNewInfo(BibEntry originalEntry, BibEntry fetchedEntry, NamedCompound ce) { @@ -188,6 +151,47 @@ private void removeField(BibEntry entry, Field field, NamedCompound ce) { ce.addEdit(new UndoableFieldChange(entry, field, originalValue.orElse(null), null)); } + private void handleFetchException(Exception exception, IdBasedFetcher fetcher) { + LOGGER.error("Error while fetching bibliographic information", exception); + String fetcherName = fetcher.getName(); + String errorMessage; + + if (exception instanceof FetcherClientException) { + errorMessage = Localization.lang("No data was found for the identifier"); + } else if (exception instanceof FetcherServerException) { + errorMessage = Localization.lang("Server not available"); + } else { + errorMessage = Localization.lang("Error occurred %0", exception.getMessage()); + } + + notificationService.notify( + Localization.lang("Error fetching from %0: %1", fetcherName, errorMessage) + ); + } + + private void processFetchedEntry(Optional fetchedEntry, Field field, BibEntry originalEntry) { + ImportCleanup cleanup = ImportCleanup.targeting(bibDatabaseContext.getMode(), preferences.getFieldPreferences()); + fetchedEntry.ifPresentOrElse( + entry -> { + cleanup.doPostCleanup(entry); + mergeWithoutDialog(originalEntry, entry); + }, + () -> notificationService.notify( + Localization.lang("Cannot get info based on given %0: %1", field.getDisplayName(), originalEntry.getField(field).orElse("")) + ) + ); + } + + private void mergeWithoutDialog(BibEntry originalEntry, BibEntry fetchedEntry) { + NamedCompound ce = new NamedCompound(Localization.lang("Merge entry without user interaction")); + + updateEntryTypeIfDifferent(originalEntry, fetchedEntry, ce); + updateFieldsWithNewInfo(originalEntry, fetchedEntry, ce); + removeObsoleteFields(originalEntry, fetchedEntry, ce); + + finalizeMerge(ce, originalEntry); + } + private void finalizeMerge(NamedCompound ce, BibEntry entry) { String citationKey = entry.getCitationKey().orElse(entry.getAuthorTitleYear(40)); String message = ce.hasEdits() @@ -198,7 +202,7 @@ private void finalizeMerge(NamedCompound ce, BibEntry entry) { ce.end(); undoManager.addEdit(ce); } - dialogService.notify(message); + notificationService.notify(message); } private Set getFields(BibEntry entry) { @@ -224,61 +228,4 @@ private void updateEntryTypeIfDifferent(BibEntry originalEntry, BibEntry fetched ce.addEdit(new UndoableChangeType(originalEntry, oldType, newType)); } } - - private void showMergeDialog(BibEntry originalEntry, BibEntry fetchedEntry, WebFetcher fetcher) { - MergeEntriesDialog dialog = createMergeDialog(originalEntry, fetchedEntry, fetcher); - Optional mergedEntry = showDialogAndGetResult(dialog); - - mergedEntry.ifPresentOrElse( - entry -> processMergedEntry(originalEntry, entry, fetcher), - () -> notifyCanceledMerge(originalEntry) - ); - } - - private MergeEntriesDialog createMergeDialog(BibEntry originalEntry, BibEntry fetchedEntry, WebFetcher fetcher) { - MergeEntriesDialog dialog = new MergeEntriesDialog(originalEntry, fetchedEntry, preferences); - 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())); - return dialog; - } - - private Optional showDialogAndGetResult(MergeEntriesDialog dialog) { - return dialogService.showCustomDialogAndWait(dialog) - .map(EntriesMergeResult::mergedEntry); - } - - private void processMergedEntry(BibEntry originalEntry, BibEntry mergedEntry, WebFetcher fetcher) { - NamedCompound ce = new NamedCompound(Localization.lang("Merge entry with %0 information", fetcher.getName())); - - updateEntryTypeIfDifferent(originalEntry, mergedEntry, ce); - updateFieldsWithNewInfo(originalEntry, mergedEntry, ce); - removeObsoleteFields(originalEntry, mergedEntry, ce); - - finalizeMerge(ce, originalEntry); - } - - private void notifyCanceledMerge(BibEntry entry) { - String citationKey = entry.getCitationKey().orElse(entry.getAuthorTitleYear(40)); - dialogService.notify(Localization.lang("Canceled merging entries") + " [" + citationKey + "]"); - } - - public void fetchAndMerge(BibEntry entry, EntryBasedFetcher fetcher) { - BackgroundTask.wrap(() -> fetcher.performSearch(entry).stream().findFirst()) - .onSuccess(fetchedEntry -> fetchedEntry - .map(fe -> { - ImportCleanup cleanup = ImportCleanup.targeting(bibDatabaseContext.getMode(), preferences.getFieldPreferences()); - cleanup.doPostCleanup(fe); - return fe; - }) - .ifPresentOrElse( - fe -> showMergeDialog(entry, fe, fetcher), - () -> dialogService.notify(Localization.lang("Could not find any bibliographic information.")) - )) - .onFailure(exception -> { - LOGGER.error("Error while fetching entry with {} ", fetcher.getName(), exception); - dialogService.showErrorDialogAndWait(Localization.lang("Error while fetching from %0", fetcher.getName()), exception); - }) - .executeWith(taskExecutor); - } }