diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index cbcea1392f8..d9aad22bfc7 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -122,6 +122,7 @@ import org.jabref.logic.autosaveandbackup.AutosaveManager; import org.jabref.logic.autosaveandbackup.BackupManager; import org.jabref.logic.citationstyle.CitationStyleOutputFormat; +import org.jabref.logic.exporter.GlobalSaveManager; import org.jabref.logic.importer.IdFetcher; import org.jabref.logic.importer.ImportCleanup; import org.jabref.logic.importer.ParserResult; @@ -445,7 +446,7 @@ public boolean quit() { context.getDBMSSynchronizer().closeSharedDatabase(); context.clearDBMSSynchronizer(); } - SaveDatabaseAction.shutdown(context); + GlobalSaveManager.shutdown(context); BackupManager.shutdown(context); context.getDatabasePath().map(Path::toAbsolutePath).map(Path::toString).ifPresent(filenames::add); } @@ -1255,7 +1256,7 @@ private boolean confirmClose(BasePanel panel) { if (response.isPresent() && response.get().equals(saveChanges)) { // The user wants to save. try { - SaveDatabaseAction saveAction = SaveDatabaseAction.create(panel, Globals.prefs, Globals.entryTypesManager); + SaveDatabaseAction saveAction = new SaveDatabaseAction(panel, Globals.prefs, Globals.entryTypesManager); if (saveAction.save()) { return true; @@ -1295,7 +1296,7 @@ private void closeTab(BasePanel panel) { removeTab(panel); } - SaveDatabaseAction.shutdown(context); + GlobalSaveManager.shutdown(context); BackupManager.shutdown(context); } diff --git a/src/main/java/org/jabref/gui/dialogs/AutosaveUiManager.java b/src/main/java/org/jabref/gui/dialogs/AutosaveUiManager.java index 476ed1f381b..3ff39487898 100644 --- a/src/main/java/org/jabref/gui/dialogs/AutosaveUiManager.java +++ b/src/main/java/org/jabref/gui/dialogs/AutosaveUiManager.java @@ -25,7 +25,7 @@ public AutosaveUiManager(BasePanel panel) { @Subscribe public void listen(@SuppressWarnings("unused") AutosaveEvent event) { try { - SaveDatabaseAction saveAction = SaveDatabaseAction.create(panel, Globals.prefs, Globals.entryTypesManager); + SaveDatabaseAction saveAction = new SaveDatabaseAction(panel, Globals.prefs, Globals.entryTypesManager); saveAction.save(SaveDatabaseAction.SaveDatabaseMode.SILENT); } catch (Throwable e) { LOGGER.error("Problem occurred while saving.", e); diff --git a/src/main/java/org/jabref/gui/exporter/SaveAction.java b/src/main/java/org/jabref/gui/exporter/SaveAction.java index 6b83910e694..e283bf29b39 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveAction.java @@ -32,7 +32,7 @@ public SaveAction(SaveMethod saveMethod, JabRefFrame frame, StateManager stateMa @Override public void execute() { - SaveDatabaseAction saveDatabaseAction = SaveDatabaseAction.create(frame.getCurrentBasePanel(), + SaveDatabaseAction saveDatabaseAction = new SaveDatabaseAction(frame.getCurrentBasePanel(), Globals.prefs, Globals.entryTypesManager); diff --git a/src/main/java/org/jabref/gui/exporter/SaveAllAction.java b/src/main/java/org/jabref/gui/exporter/SaveAllAction.java index 529d7667a79..4c2c1dd69a3 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveAllAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveAllAction.java @@ -22,7 +22,7 @@ public void execute() { dialogService.notify(Localization.lang("Saving all libraries...")); for (BasePanel panel : frame.getBasePanelList()) { - SaveDatabaseAction saveDatabaseAction = SaveDatabaseAction.create(panel, Globals.prefs, Globals.entryTypesManager); + SaveDatabaseAction saveDatabaseAction = new SaveDatabaseAction(panel, Globals.prefs, Globals.entryTypesManager); boolean saveResult = saveDatabaseAction.save(); if (!saveResult) { dialogService.notify(Localization.lang("Could not save file.")); diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 0bedcbdfaa5..fe961b4c0bf 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -1,10 +1,7 @@ package org.jabref.gui.exporter; -import java.io.IOException; import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; import java.nio.file.Path; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Optional; @@ -27,15 +24,13 @@ import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.autosaveandbackup.AutosaveManager; import org.jabref.logic.autosaveandbackup.BackupManager; -import org.jabref.logic.exporter.AtomicFileWriter; -import org.jabref.logic.exporter.BibtexDatabaseWriter; +import org.jabref.logic.exporter.GlobalSaveManager; import org.jabref.logic.exporter.SaveException; import org.jabref.logic.exporter.SavePreferences; import org.jabref.logic.l10n.Encodings; import org.jabref.logic.l10n.Localization; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; -import org.jabref.logic.util.DelayTaskThrottler; import org.jabref.logic.util.StandardFileType; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabaseContext; @@ -63,34 +58,17 @@ public class SaveDatabaseAction { private final DialogService dialogService; private final JabRefPreferences preferences; private final BibEntryTypesManager entryTypesManager; - private final DelayTaskThrottler> throttler; public enum SaveDatabaseMode { SILENT, NORMAL } - private SaveDatabaseAction(BasePanel panel, JabRefPreferences preferences, BibEntryTypesManager entryTypesManager) { + public SaveDatabaseAction(BasePanel panel, JabRefPreferences preferences, BibEntryTypesManager entryTypesManager) { this.panel = panel; this.frame = panel.frame(); this.dialogService = frame.getDialogService(); this.preferences = preferences; this.entryTypesManager = entryTypesManager; - this.throttler = new DelayTaskThrottler<>(1500); - } - - public static void shutdown(BibDatabaseContext context) { - runningInstances.stream().filter(instance -> instance.panel.getBibDatabaseContext() == context).forEach(SaveDatabaseAction::shutdown); - runningInstances.removeIf(instance -> instance.panel.getBibDatabaseContext() == context); - } - - private void shutdown() { - this.throttler.shutdown(); - } - - public static SaveDatabaseAction create(BasePanel panel, JabRefPreferences preferences, BibEntryTypesManager entryTypesManager) { - SaveDatabaseAction saveAction = new SaveDatabaseAction(panel, preferences, entryTypesManager); - runningInstances.add(saveAction); - return saveAction; } public boolean save() { @@ -241,16 +219,17 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding, SavePreferences.DatabaseSaveType saveType) throws SaveException { + GlobalSaveManager manager = GlobalSaveManager.create(panel, preferences, entryTypesManager); SavePreferences preferences = this.preferences.getSavePreferences() .withEncoding(encoding) .withSaveType(saveType); - Consumer> consumer = f -> panel.registerUndoableChanges(f); + Consumer> consumer = fieldChanges -> panel.registerUndoableChanges(fieldChanges); - var future = throttler.scheduleTask(() -> saveThrotteld(file, selectedOnly, encoding, saveType, panel.getBibDatabaseContext(), consumer)); + var future = manager.save(file, selectedOnly, encoding, saveType, panel.getBibDatabaseContext(), consumer); Set characters; try { - characters = future.get(); + characters =future.get(); if (!characters.isEmpty()) { saveWithDifferentEncoding(file, selectedOnly, preferences.getEncoding(), characters, saveType); } @@ -263,33 +242,6 @@ private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding, } - private Set saveThrotteld(Path file, boolean selectedOnly, Charset encoding, SavePreferences.DatabaseSaveType saveType, BibDatabaseContext context, Consumer> consumeFieldChanges) throws SaveException { - SavePreferences preferences = this.preferences.getSavePreferences() - .withEncoding(encoding) - .withSaveType(saveType); - - try (AtomicFileWriter fileWriter = new AtomicFileWriter(file, preferences.getEncoding(), preferences.shouldMakeBackup())) { - BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter(fileWriter, preferences, entryTypesManager); - - if (selectedOnly) { - databaseWriter.savePartOfDatabase(context, panel.getSelectedEntries()); - } else { - databaseWriter.saveDatabase(context); - } - - consumeFieldChanges.accept(databaseWriter.getSaveActionsFieldChanges()); - - if (fileWriter.hasEncodingProblems()) { - return fileWriter.getEncodingProblems(); - } - } catch (UnsupportedCharsetException ex) { - throw new SaveException(Localization.lang("Character encoding '%0' is not supported.", encoding.displayName()), ex); - } catch (IOException ex) { - throw new SaveException("Problems saving: " + ex, ex); - } - - return Collections.emptySet(); - } private void saveWithDifferentEncoding(Path file, boolean selectedOnly, Charset encoding, Set encodingProblems, SavePreferences.DatabaseSaveType saveType) throws SaveException { DialogPane pane = new DialogPane(); diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java index b7927283b60..845732f020a 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java @@ -166,7 +166,7 @@ private boolean openSharedDatabase(DBMSConnectionProperties connectionProperties if (!folder.getValue().isEmpty()) { try { - SaveDatabaseAction.create(panel, Globals.prefs, Globals.entryTypesManager).saveAs(Path.of(folder.getValue())); + new SaveDatabaseAction(panel, Globals.prefs, Globals.entryTypesManager).saveAs(Path.of(folder.getValue())); } catch (Throwable e) { LOGGER.error("Error while saving the database", e); } diff --git a/src/main/java/org/jabref/logic/exporter/GlobalSaveManager.java b/src/main/java/org/jabref/logic/exporter/GlobalSaveManager.java new file mode 100644 index 00000000000..bdddf5f15dc --- /dev/null +++ b/src/main/java/org/jabref/logic/exporter/GlobalSaveManager.java @@ -0,0 +1,88 @@ +package org.jabref.logic.exporter; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.function.Consumer; + +import org.jabref.gui.BasePanel; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.DelayTaskThrottler; +import org.jabref.model.FieldChange; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.BibEntryTypesManager; +import org.jabref.preferences.JabRefPreferences; + +public class GlobalSaveManager { + + private static Set runningInstances = new HashSet<>(); + + private final DelayTaskThrottler> throttler = new DelayTaskThrottler<>(1500); + private final BibDatabaseContext bibDatabaseContext; + private final List selectedEntries; + private final JabRefPreferences preferences; + private final BibEntryTypesManager entryTypesManager; + + private GlobalSaveManager(BasePanel panel, JabRefPreferences preferences, BibEntryTypesManager entryTypesManager) { + this.bibDatabaseContext = panel.getBibDatabaseContext(); + this.selectedEntries = panel.getSelectedEntries(); + this.preferences = preferences; + this.entryTypesManager = entryTypesManager; + + } + + public static void shutdown(BibDatabaseContext context) { + runningInstances.stream().filter(instance -> instance.bibDatabaseContext == context).forEach(GlobalSaveManager::shutdown); + runningInstances.removeIf(instance -> instance.bibDatabaseContext == context); + } + + public static GlobalSaveManager create(BasePanel panel, JabRefPreferences preferences, BibEntryTypesManager entryTypesManager) { + GlobalSaveManager saveAction = new GlobalSaveManager(panel, preferences, entryTypesManager); + runningInstances.add(saveAction); + return saveAction; + } + + private void shutdown() { + this.throttler.shutdown(); + + } + + public Future> save(Path file, boolean selectedOnly, Charset encoding, SavePreferences.DatabaseSaveType saveType, BibDatabaseContext context, Consumer> consumeFieldChanges) throws SaveException { + return throttler.scheduleTask(() -> saveThrotteld(file, selectedOnly, encoding, saveType, context, consumeFieldChanges)); + } + + private Set saveThrotteld(Path file, boolean selectedOnly, Charset encoding, SavePreferences.DatabaseSaveType saveType, BibDatabaseContext context, Consumer> consumeFieldChanges) throws SaveException { + SavePreferences savePrefs = this.preferences.getSavePreferences() + .withEncoding(encoding) + .withSaveType(saveType); + + try (AtomicFileWriter fileWriter = new AtomicFileWriter(file, savePrefs.getEncoding(), savePrefs.shouldMakeBackup())) { + BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter(fileWriter, savePrefs, entryTypesManager); + + if (selectedOnly) { + databaseWriter.savePartOfDatabase(context, selectedEntries); + } else { + databaseWriter.saveDatabase(context); + } + + consumeFieldChanges.accept(databaseWriter.getSaveActionsFieldChanges()); + + if (fileWriter.hasEncodingProblems()) { + return fileWriter.getEncodingProblems(); + } + } catch (UnsupportedCharsetException ex) { + throw new SaveException(Localization.lang("Character encoding '%0' is not supported.", encoding.displayName()), ex); + } catch (IOException ex) { + throw new SaveException("Problems saving: " + ex, ex); + } + + return Collections.emptySet(); + } +} diff --git a/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java b/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java index ec54a7fad46..4ab5f350881 100644 --- a/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java +++ b/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java @@ -59,7 +59,7 @@ public void setUp() { when(basePanel.getBibDatabaseContext()).thenReturn(dbContext); when(jabRefFrame.getDialogService()).thenReturn(dialogService); - saveDatabaseAction = spy(SaveDatabaseAction.create(basePanel, preferences, mock(BibEntryTypesManager.class))); + saveDatabaseAction = spy(new SaveDatabaseAction(basePanel, preferences, mock(BibEntryTypesManager.class))); } @Test @@ -129,7 +129,7 @@ private SaveDatabaseAction createSaveDatabaseActionForBibDatabase(BibDatabase da when(basePanel.getBibDatabaseContext()).thenReturn(dbContext); when(basePanel.getUndoManager()).thenReturn(mock(CountingUndoManager.class)); when(basePanel.getBibDatabaseContext()).thenReturn(dbContext); - saveDatabaseAction = SaveDatabaseAction.create(basePanel, preferences, mock(BibEntryTypesManager.class)); + saveDatabaseAction = new SaveDatabaseAction(basePanel, preferences, mock(BibEntryTypesManager.class)); return saveDatabaseAction; }