From 30108dc0e91ef3698d9c5ef35395143a7d30d172 Mon Sep 17 00:00:00 2001 From: Houssem Nasri Date: Thu, 11 Aug 2022 22:46:40 +0100 Subject: [PATCH 01/52] Fix dead link (#9047) --- docs/decisions/0001-use-crowdin-for-translations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/decisions/0001-use-crowdin-for-translations.md b/docs/decisions/0001-use-crowdin-for-translations.md index 5ded77562e0..af8ba405b1b 100644 --- a/docs/decisions/0001-use-crowdin-for-translations.md +++ b/docs/decisions/0001-use-crowdin-for-translations.md @@ -13,7 +13,7 @@ The JabRef UI is offered in multiple languages. It should be easy for translator * Use [Crowdin](http://crowdin.com/) * Use [popeye](https://github.com/JabRef/popeye) * Use [Lingohub](https://lingohub.com/) -* Keep current GitHub flow. See the [Step-by-step guide](https://docs.jabref.org/faq/how-to-translate-the-ui). +* Keep current GitHub flow. See the [Step-by-step guide](https://docs.jabref.org/contributing/how-to-translate-the-ui). ## Decision Outcome From 507a2635f40807d8882efdbe5c68454e00917c16 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Fri, 12 Aug 2022 14:22:12 +0200 Subject: [PATCH 02/52] ExternalFileTypes singleton refactor (#9044) * Simplify singleton * Fixed factory methods * Reworded for consistency * Moved externalFileTypes to preferences * Added deprecated notice * Moved preferences to FilePreferences * Extract static call in ExternalFileTypes methods * Made util functions static * Removed call to getExternalFileTypes * Removed singleton * Added tests * Cleanup * Fixed test --- .../org/jabref/cli/ArgumentProcessor.java | 4 +- .../org/jabref/gui/EntryTypeViewModel.java | 2 - src/main/java/org/jabref/gui/JabRefFrame.java | 3 +- src/main/java/org/jabref/gui/LibraryTab.java | 11 +- .../BibtexExtractorViewModel.java | 2 - .../org/jabref/gui/desktop/JabRefDesktop.java | 2 +- .../java/org/jabref/gui/desktop/os/Linux.java | 3 +- .../java/org/jabref/gui/desktop/os/OSX.java | 3 +- .../org/jabref/gui/desktop/os/Windows.java | 3 +- .../gui/entryeditor/DeprecatedFieldsTab.java | 4 +- .../jabref/gui/entryeditor/EntryEditor.java | 20 ++- .../gui/entryeditor/FieldsEditorTab.java | 6 +- .../gui/entryeditor/OptionalFields2Tab.java | 3 - .../gui/entryeditor/OptionalFieldsTab.java | 3 - .../entryeditor/OptionalFieldsTabBase.java | 3 - .../gui/entryeditor/OtherFieldsTab.java | 3 - .../jabref/gui/entryeditor/PreviewTab.java | 8 +- .../gui/entryeditor/RequiredFieldsTab.java | 4 +- .../gui/entryeditor/UserDefinedFieldsTab.java | 6 +- .../externalfiles/AutoLinkFilesAction.java | 4 +- .../externalfiles/AutoSetFileLinksUtil.java | 14 +- .../externalfiles/DownloadFullTextAction.java | 4 +- .../ExternalFilesEntryLinker.java | 6 +- .../externalfiles/FileExtensionViewModel.java | 9 +- .../gui/externalfiles/ImportHandler.java | 4 +- .../UnlinkedFilesDialogView.java | 3 +- .../UnlinkedFilesDialogViewModel.java | 9 +- .../externalfiletype/ExternalFileType.java | 17 +- .../externalfiletype/ExternalFileTypes.java | 150 +++++++----------- .../gui/fieldeditors/LinkedFileViewModel.java | 20 +-- .../LinkedFilesEditorViewModel.java | 33 ++-- .../org/jabref/gui/fieldeditors/URLUtil.java | 5 +- .../importer/GenerateEntryFromIdAction.java | 11 +- .../gui/importer/ImportEntriesViewModel.java | 5 +- .../gui/linkedfile/AttachFileAction.java | 6 +- .../linkedfile/LinkedFileEditDialogView.java | 5 +- .../LinkedFilesEditDialogViewModel.java | 17 +- .../org/jabref/gui/maintable/CellFactory.java | 5 +- .../org/jabref/gui/maintable/MainTable.java | 5 +- .../gui/maintable/MainTableColumnFactory.java | 8 +- .../gui/maintable/OpenExternalFileAction.java | 7 +- .../gui/maintable/OpenFolderAction.java | 9 +- .../gui/maintable/columns/FileColumn.java | 20 +-- .../StyleSelectDialogViewModel.java | 2 +- .../ExternalFileTypesTab.java | 3 +- .../ExternalFileTypesTabViewModel.java | 12 +- .../ProtectedTermsTabViewModel.java | 4 +- .../preferences/table/TableTabViewModel.java | 9 +- .../org/jabref/gui/preview/PreviewPanel.java | 4 +- .../jabref/gui/search/GlobalSearchBar.java | 3 +- .../gui/search/GlobalSearchResultDialog.java | 7 +- .../jabref/gui/search/SearchResultsTable.java | 5 +- .../jabref/preferences/FilePreferences.java | 15 +- .../jabref/preferences/JabRefPreferences.java | 17 +- .../preferences/PreferencesService.java | 5 - .../AutoSetFileLinksUtilTest.java | 17 +- .../ExternalFileTypesTest.java | 121 ++++++++++++++ .../fieldeditors/LinkedFileViewModelTest.java | 39 ++--- 58 files changed, 370 insertions(+), 362 deletions(-) create mode 100644 src/test/java/org/jabref/gui/externalfiletype/ExternalFileTypesTest.java diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index f1aaa0653d7..e99e62fe40f 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -15,7 +15,6 @@ import org.jabref.gui.Globals; import org.jabref.gui.externalfiles.AutoSetFileLinksUtil; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.undo.NamedCompound; import org.jabref.logic.JabRefException; import org.jabref.logic.bibtex.FieldWriterPreferences; @@ -640,8 +639,7 @@ private void automaticallySetFileLinks(List loaded) { AutoSetFileLinksUtil util = new AutoSetFileLinksUtil( parserResult.getDatabaseContext(), preferencesService.getFilePreferences(), - preferencesService.getAutoLinkPreferences(), - ExternalFileTypes.getInstance()); + preferencesService.getAutoLinkPreferences()); util.linkAssociatedFiles(database.getEntries(), new NamedCompound("")); } } diff --git a/src/main/java/org/jabref/gui/EntryTypeViewModel.java b/src/main/java/org/jabref/gui/EntryTypeViewModel.java index 4e18e4d87c0..7e08b6857e2 100644 --- a/src/main/java/org/jabref/gui/EntryTypeViewModel.java +++ b/src/main/java/org/jabref/gui/EntryTypeViewModel.java @@ -15,7 +15,6 @@ import javafx.concurrent.Worker; import org.jabref.gui.externalfiles.ImportHandler; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.importer.NewEntryAction; import org.jabref.logic.importer.FetcherClientException; import org.jabref.logic.importer.FetcherException; @@ -169,7 +168,6 @@ public void runFetcherWorker() { ImportHandler handler = new ImportHandler( libraryTab.getBibDatabaseContext(), - ExternalFileTypes.getInstance(), preferencesService, Globals.getFileUpdateMonitor(), libraryTab.getUndoManager(), diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 638a7761f10..4d07c12aca2 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -81,7 +81,6 @@ import org.jabref.gui.externalfiles.AutoLinkFilesAction; import org.jabref.gui.externalfiles.DownloadFullTextAction; import org.jabref.gui.externalfiles.FindUnlinkedFilesAction; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.help.AboutAction; import org.jabref.gui.help.ErrorConsoleAction; import org.jabref.gui.help.HelpAction; @@ -1143,7 +1142,7 @@ private void trackOpenNewDatabase(LibraryTab libraryTab) { public LibraryTab addTab(BibDatabaseContext databaseContext, boolean raisePanel) { Objects.requireNonNull(databaseContext); - LibraryTab libraryTab = new LibraryTab(this, prefs, stateManager, themeManager, databaseContext, ExternalFileTypes.getInstance(), importFormatReader); + LibraryTab libraryTab = new LibraryTab(this, prefs, stateManager, themeManager, databaseContext, importFormatReader); addTab(libraryTab, raisePanel); return libraryTab; } diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index f037135f6d9..ad40925cacc 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -29,7 +29,6 @@ import org.jabref.gui.collab.DatabaseChangeMonitor; import org.jabref.gui.dialogs.AutosaveUiManager; import org.jabref.gui.entryeditor.EntryEditor; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.importer.actions.OpenDatabaseAction; import org.jabref.gui.maintable.MainTable; import org.jabref.gui.maintable.MainTableDataModel; @@ -84,7 +83,6 @@ public class LibraryTab extends Tab { private static final Logger LOGGER = LoggerFactory.getLogger(LibraryTab.class); private final JabRefFrame frame; private final CountingUndoManager undoManager; - private final ExternalFileTypes externalFileTypes; private final DialogService dialogService; private final PreferencesService preferencesService; private final StateManager stateManager; @@ -122,11 +120,9 @@ public LibraryTab(JabRefFrame frame, StateManager stateManager, ThemeManager themeManager, BibDatabaseContext bibDatabaseContext, - ExternalFileTypes externalFileTypes, ImportFormatReader importFormatReader) { this.frame = Objects.requireNonNull(frame); this.bibDatabaseContext = Objects.requireNonNull(bibDatabaseContext); - this.externalFileTypes = Objects.requireNonNull(externalFileTypes); this.undoManager = frame.getUndoManager(); this.dialogService = frame.getDialogService(); this.preferencesService = Objects.requireNonNull(preferencesService); @@ -156,7 +152,7 @@ public LibraryTab(JabRefFrame frame, this.getDatabase().registerListener(new UpdateTimestampListener(preferencesService)); - this.entryEditor = new EntryEditor(this, externalFileTypes); + this.entryEditor = new EntryEditor(this); // set LibraryTab ID for drag'n'drop // ID content doesn't matter, we only need different tabs to have different ID @@ -257,7 +253,7 @@ public void feedData(BibDatabaseContext bibDatabaseContext) { this.getDatabase().registerListener(new UpdateTimestampListener(preferencesService)); - this.entryEditor = new EntryEditor(this, externalFileTypes); + this.entryEditor = new EntryEditor(this); Platform.runLater(() -> { EasyBind.subscribe(changedProperty, this::updateTabTitle); @@ -488,7 +484,6 @@ private void createMainTable() { preferencesService, dialogService, stateManager, - externalFileTypes, Globals.getKeyPrefs(), Globals.getClipboardManager(), Globals.IMPORT_FORMAT_READER); @@ -808,7 +803,7 @@ public LibraryTab createLibraryTab(JabRefFrame frame, PreferencesService prefere BibDatabaseContext context = new BibDatabaseContext(); context.setDatabasePath(file); - LibraryTab newTab = new LibraryTab(frame, preferencesService, stateManager, themeManager, context, ExternalFileTypes.getInstance(), importFormatReader); + LibraryTab newTab = new LibraryTab(frame, preferencesService, stateManager, themeManager, context, importFormatReader); newTab.setDataLoadingTask(dataLoadingTask); dataLoadingTask.onRunning(newTab::onDatabaseLoadingStarted) diff --git a/src/main/java/org/jabref/gui/bibtexextractor/BibtexExtractorViewModel.java b/src/main/java/org/jabref/gui/bibtexextractor/BibtexExtractorViewModel.java index 8224873ad70..61db2e93b47 100644 --- a/src/main/java/org/jabref/gui/bibtexextractor/BibtexExtractorViewModel.java +++ b/src/main/java/org/jabref/gui/bibtexextractor/BibtexExtractorViewModel.java @@ -13,7 +13,6 @@ import org.jabref.gui.Globals; import org.jabref.gui.StateManager; import org.jabref.gui.externalfiles.ImportHandler; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.importer.FetcherException; @@ -52,7 +51,6 @@ public BibtexExtractorViewModel(BibDatabaseContext bibdatabaseContext, this.taskExecutor = taskExecutor; this.importHandler = new ImportHandler( bibdatabaseContext, - ExternalFileTypes.getInstance(), preferencesService, fileUpdateMonitor, undoManager, diff --git a/src/main/java/org/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/org/jabref/gui/desktop/JabRefDesktop.java index 96bc258e134..517ffc1689d 100644 --- a/src/main/java/org/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/org/jabref/gui/desktop/JabRefDesktop.java @@ -219,7 +219,7 @@ public static void openFolderAndSelectFile(Path fileLink, PreferencesService pre * @param url the URL to open */ public static void openBrowser(String url) throws IOException { - Optional fileType = ExternalFileTypes.getInstance().getExternalFileTypeByExt("html"); + Optional fileType = ExternalFileTypes.getExternalFileTypeByExt("html", Globals.prefs.getFilePreferences()); openExternalFilePlatformIndependent(fileType, url); } diff --git a/src/main/java/org/jabref/gui/desktop/os/Linux.java b/src/main/java/org/jabref/gui/desktop/os/Linux.java index c522f172c55..289efb4f576 100644 --- a/src/main/java/org/jabref/gui/desktop/os/Linux.java +++ b/src/main/java/org/jabref/gui/desktop/os/Linux.java @@ -12,6 +12,7 @@ import org.jabref.architecture.AllowedToUseAwt; import org.jabref.gui.DialogService; +import org.jabref.gui.Globals; import org.jabref.gui.JabRefExecutorService; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; @@ -48,7 +49,7 @@ private void nativeOpenFile(String filePath) { @Override public void openFile(String filePath, String fileType) throws IOException { - Optional type = ExternalFileTypes.getInstance().getExternalFileTypeByExt(fileType); + Optional type = ExternalFileTypes.getExternalFileTypeByExt(fileType, Globals.prefs.getFilePreferences()); String viewer; if (type.isPresent() && !type.get().getOpenWithApplication().isEmpty()) { diff --git a/src/main/java/org/jabref/gui/desktop/os/OSX.java b/src/main/java/org/jabref/gui/desktop/os/OSX.java index 2bb731619fa..d7a3c6cd710 100644 --- a/src/main/java/org/jabref/gui/desktop/os/OSX.java +++ b/src/main/java/org/jabref/gui/desktop/os/OSX.java @@ -6,6 +6,7 @@ import org.jabref.architecture.AllowedToUseAwt; import org.jabref.gui.DialogService; +import org.jabref.gui.Globals; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; @@ -14,7 +15,7 @@ public class OSX implements NativeDesktop { @Override public void openFile(String filePath, String fileType) throws IOException { - Optional type = ExternalFileTypes.getInstance().getExternalFileTypeByExt(fileType); + Optional type = ExternalFileTypes.getExternalFileTypeByExt(fileType, Globals.prefs.getFilePreferences()); if (type.isPresent() && !type.get().getOpenWithApplication().isEmpty()) { openFileWithApplication(filePath, type.get().getOpenWithApplication()); } else { diff --git a/src/main/java/org/jabref/gui/desktop/os/Windows.java b/src/main/java/org/jabref/gui/desktop/os/Windows.java index a5a6acfe79a..d85722740d6 100644 --- a/src/main/java/org/jabref/gui/desktop/os/Windows.java +++ b/src/main/java/org/jabref/gui/desktop/os/Windows.java @@ -7,6 +7,7 @@ import java.util.Optional; import org.jabref.gui.DialogService; +import org.jabref.gui.Globals; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; @@ -15,7 +16,7 @@ public class Windows implements NativeDesktop { @Override public void openFile(String filePath, String fileType) throws IOException { - Optional type = ExternalFileTypes.getInstance().getExternalFileTypeByExt(fileType); + Optional type = ExternalFileTypes.getExternalFileTypeByExt(fileType, Globals.prefs.getFilePreferences()); if (type.isPresent() && !type.get().getOpenWithApplication().isEmpty()) { openFileWithApplication(filePath, type.get().getOpenWithApplication()); diff --git a/src/main/java/org/jabref/gui/entryeditor/DeprecatedFieldsTab.java b/src/main/java/org/jabref/gui/entryeditor/DeprecatedFieldsTab.java index 7127c0af919..d5bc20da9e6 100644 --- a/src/main/java/org/jabref/gui/entryeditor/DeprecatedFieldsTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/DeprecatedFieldsTab.java @@ -12,7 +12,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProviders; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.TaskExecutor; @@ -39,10 +38,9 @@ public DeprecatedFieldsTab(BibDatabaseContext databaseContext, ThemeManager themeManager, IndexingTaskManager indexingTaskManager, BibEntryTypesManager entryTypesManager, - ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationRepository journalAbbreviationRepository) { - super(false, databaseContext, suggestionProviders, undoManager, dialogService, preferences, stateManager, themeManager, externalFileTypes, taskExecutor, journalAbbreviationRepository, indexingTaskManager); + super(false, databaseContext, suggestionProviders, undoManager, dialogService, preferences, stateManager, themeManager, taskExecutor, journalAbbreviationRepository, indexingTaskManager); this.entryTypesManager = entryTypesManager; setText(Localization.lang("Deprecated fields")); diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 5066e762b1c..b5f2d72ca39 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -34,7 +34,6 @@ import org.jabref.gui.entryeditor.fileannotationtab.FileAnnotationTab; import org.jabref.gui.entryeditor.fileannotationtab.FulltextSearchResultsTab; import org.jabref.gui.externalfiles.ExternalFilesEntryLinker; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.help.HelpAction; import org.jabref.gui.importer.GrobidOptInDialogHelper; import org.jabref.gui.keyboard.KeyBinding; @@ -113,7 +112,7 @@ public class EntryEditor extends BorderPane { private final List entryEditorTabs = new LinkedList<>(); - public EntryEditor(LibraryTab libraryTab, ExternalFileTypes externalFileTypes) { + public EntryEditor(LibraryTab libraryTab) { this.libraryTab = libraryTab; this.databaseContext = libraryTab.getBibDatabaseContext(); @@ -122,8 +121,7 @@ public EntryEditor(LibraryTab libraryTab, ExternalFileTypes externalFileTypes) { .load(); this.entryEditorPreferences = preferencesService.getEntryEditorPreferences(); - this.fileLinker = new ExternalFilesEntryLinker(externalFileTypes, preferencesService.getFilePreferences(), - databaseContext); + this.fileLinker = new ExternalFilesEntryLinker(preferencesService.getFilePreferences(), databaseContext); EasyBind.subscribe(tabbed.getSelectionModel().selectedItemProperty(), tab -> { EntryEditorTab activeTab = (EntryEditorTab) tab; @@ -242,22 +240,22 @@ private void navigateToNextEntry() { private List createTabs() { // Preview tab - entryEditorTabs.add(new PreviewTab(databaseContext, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), ExternalFileTypes.getInstance())); + entryEditorTabs.add(new PreviewTab(databaseContext, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager())); // Required fields - entryEditorTabs.add(new RequiredFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, ExternalFileTypes.getInstance(), taskExecutor, journalAbbreviationRepository)); + entryEditorTabs.add(new RequiredFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository)); // Optional fields - entryEditorTabs.add(new OptionalFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, ExternalFileTypes.getInstance(), taskExecutor, journalAbbreviationRepository)); - entryEditorTabs.add(new OptionalFields2Tab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, ExternalFileTypes.getInstance(), taskExecutor, journalAbbreviationRepository)); - entryEditorTabs.add(new DeprecatedFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, ExternalFileTypes.getInstance(), taskExecutor, journalAbbreviationRepository)); + entryEditorTabs.add(new OptionalFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository)); + entryEditorTabs.add(new OptionalFields2Tab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository)); + entryEditorTabs.add(new DeprecatedFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository)); // Other fields - entryEditorTabs.add(new OtherFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, ExternalFileTypes.getInstance(), taskExecutor, journalAbbreviationRepository)); + entryEditorTabs.add(new OtherFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository)); // General fields from preferences for (Map.Entry> tab : entryEditorPreferences.getEntryEditorTabList().entrySet()) { - entryEditorTabs.add(new UserDefinedFieldsTab(tab.getKey(), tab.getValue(), databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, ExternalFileTypes.getInstance(), taskExecutor, journalAbbreviationRepository)); + entryEditorTabs.add(new UserDefinedFieldsTab(tab.getKey(), tab.getValue(), databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), taskExecutor, journalAbbreviationRepository)); } // Special tabs diff --git a/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java b/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java index 342a519d6b7..49fc1d8715b 100644 --- a/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java @@ -26,7 +26,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProviders; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.FieldEditorFX; import org.jabref.gui.fieldeditors.FieldEditors; import org.jabref.gui.fieldeditors.FieldNameLabel; @@ -53,7 +52,6 @@ abstract class FieldsEditorTab extends EntryEditorTab { private final DialogService dialogService; private final PreferencesService preferences; private final ThemeManager themeManager; - private final ExternalFileTypes externalFileTypes; private final TaskExecutor taskExecutor; private final JournalAbbreviationRepository journalAbbreviationRepository; private final StateManager stateManager; @@ -71,7 +69,6 @@ public FieldsEditorTab(boolean compressed, PreferencesService preferences, StateManager stateManager, ThemeManager themeManager, - ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationRepository journalAbbreviationRepository, IndexingTaskManager indexingTaskManager) { @@ -82,7 +79,6 @@ public FieldsEditorTab(boolean compressed, this.dialogService = Objects.requireNonNull(dialogService); this.preferences = Objects.requireNonNull(preferences); this.themeManager = themeManager; - this.externalFileTypes = Objects.requireNonNull(externalFileTypes); this.taskExecutor = Objects.requireNonNull(taskExecutor); this.journalAbbreviationRepository = Objects.requireNonNull(journalAbbreviationRepository); this.stateManager = stateManager; @@ -246,7 +242,7 @@ private void initPanel() { scrollPane.setFitToHeight(true); SplitPane container = new SplitPane(scrollPane); - previewPanel = new PreviewPanel(databaseContext, dialogService, externalFileTypes, preferences.getKeyBindingRepository(), preferences, stateManager, themeManager, indexingTaskManager); + previewPanel = new PreviewPanel(databaseContext, dialogService, preferences.getKeyBindingRepository(), preferences, stateManager, themeManager, indexingTaskManager); EasyBind.subscribe(preferences.getPreviewPreferences().showPreviewAsExtraTabProperty(), show -> { if (show) { container.getItems().remove(previewPanel); diff --git a/src/main/java/org/jabref/gui/entryeditor/OptionalFields2Tab.java b/src/main/java/org/jabref/gui/entryeditor/OptionalFields2Tab.java index 07090e543ee..97c38da58dd 100644 --- a/src/main/java/org/jabref/gui/entryeditor/OptionalFields2Tab.java +++ b/src/main/java/org/jabref/gui/entryeditor/OptionalFields2Tab.java @@ -5,7 +5,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProviders; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.journals.JournalAbbreviationRepository; @@ -25,7 +24,6 @@ public OptionalFields2Tab(BibDatabaseContext databaseContext, ThemeManager themeManager, IndexingTaskManager indexingTaskManager, BibEntryTypesManager entryTypesManager, - ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationRepository journalAbbreviationRepository) { super( @@ -40,7 +38,6 @@ public OptionalFields2Tab(BibDatabaseContext databaseContext, themeManager, indexingTaskManager, entryTypesManager, - externalFileTypes, taskExecutor, journalAbbreviationRepository ); diff --git a/src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTab.java b/src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTab.java index 0035e806258..93a6ff4b6f1 100644 --- a/src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTab.java @@ -5,7 +5,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProviders; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.journals.JournalAbbreviationRepository; @@ -25,7 +24,6 @@ public OptionalFieldsTab(BibDatabaseContext databaseContext, ThemeManager themeManager, IndexingTaskManager indexingTaskManager, BibEntryTypesManager entryTypesManager, - ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationRepository journalAbbreviationRepository) { super( @@ -40,7 +38,6 @@ public OptionalFieldsTab(BibDatabaseContext databaseContext, themeManager, indexingTaskManager, entryTypesManager, - externalFileTypes, taskExecutor, journalAbbreviationRepository ); diff --git a/src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTabBase.java b/src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTabBase.java index 52c88a8c809..af1a5f9f0b6 100644 --- a/src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTabBase.java +++ b/src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTabBase.java @@ -11,7 +11,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProviders; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.TaskExecutor; @@ -40,7 +39,6 @@ public OptionalFieldsTabBase(String title, ThemeManager themeManager, IndexingTaskManager indexingTaskManager, BibEntryTypesManager entryTypesManager, - ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationRepository journalAbbreviationRepository) { super(true, @@ -51,7 +49,6 @@ public OptionalFieldsTabBase(String title, preferences, stateManager, themeManager, - externalFileTypes, taskExecutor, journalAbbreviationRepository, indexingTaskManager); diff --git a/src/main/java/org/jabref/gui/entryeditor/OtherFieldsTab.java b/src/main/java/org/jabref/gui/entryeditor/OtherFieldsTab.java index 08802ceb27c..0fe1281c077 100644 --- a/src/main/java/org/jabref/gui/entryeditor/OtherFieldsTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/OtherFieldsTab.java @@ -14,7 +14,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProviders; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.TaskExecutor; @@ -44,7 +43,6 @@ public OtherFieldsTab(BibDatabaseContext databaseContext, ThemeManager themeManager, IndexingTaskManager indexingTaskManager, BibEntryTypesManager entryTypesManager, - ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationRepository journalAbbreviationRepository) { super(false, @@ -55,7 +53,6 @@ public OtherFieldsTab(BibDatabaseContext databaseContext, preferences, stateManager, themeManager, - externalFileTypes, taskExecutor, journalAbbreviationRepository, indexingTaskManager); diff --git a/src/main/java/org/jabref/gui/entryeditor/PreviewTab.java b/src/main/java/org/jabref/gui/entryeditor/PreviewTab.java index b66b3c49a18..4212506b8f6 100644 --- a/src/main/java/org/jabref/gui/entryeditor/PreviewTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/PreviewTab.java @@ -2,7 +2,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.preview.PreviewPanel; import org.jabref.gui.theme.ThemeManager; @@ -19,7 +18,6 @@ public class PreviewTab extends EntryEditorTab { private final StateManager stateManager; private final ThemeManager themeManager; private final IndexingTaskManager indexingTaskManager; - private final ExternalFileTypes externalFileTypes; private PreviewPanel previewPanel; public PreviewTab(BibDatabaseContext databaseContext, @@ -27,15 +25,13 @@ public PreviewTab(BibDatabaseContext databaseContext, PreferencesService preferences, StateManager stateManager, ThemeManager themeManager, - IndexingTaskManager indexingTaskManager, - ExternalFileTypes externalFileTypes) { + IndexingTaskManager indexingTaskManager) { this.databaseContext = databaseContext; this.dialogService = dialogService; this.preferences = preferences; this.stateManager = stateManager; this.themeManager = themeManager; this.indexingTaskManager = indexingTaskManager; - this.externalFileTypes = externalFileTypes; setGraphic(IconTheme.JabRefIcons.TOGGLE_ENTRY_PREVIEW.getGraphicNode()); setText(Localization.lang("Preview")); @@ -63,7 +59,7 @@ public boolean shouldShow(BibEntry entry) { @Override protected void bindToEntry(BibEntry entry) { if (previewPanel == null) { - previewPanel = new PreviewPanel(databaseContext, dialogService, externalFileTypes, preferences.getKeyBindingRepository(), preferences, stateManager, themeManager, indexingTaskManager); + previewPanel = new PreviewPanel(databaseContext, dialogService, preferences.getKeyBindingRepository(), preferences, stateManager, themeManager, indexingTaskManager); setContent(previewPanel); } diff --git a/src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java b/src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java index 5c078dea5b5..3451f2c8f53 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java @@ -11,7 +11,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProviders; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.TaskExecutor; @@ -40,11 +39,10 @@ public RequiredFieldsTab(BibDatabaseContext databaseContext, ThemeManager themeManager, IndexingTaskManager indexingTaskManager, BibEntryTypesManager entryTypesManager, - ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationRepository journalAbbreviationRepository) { super(false, databaseContext, suggestionProviders, undoManager, dialogService, - preferences, stateManager, themeManager, externalFileTypes, taskExecutor, journalAbbreviationRepository, indexingTaskManager); + preferences, stateManager, themeManager, taskExecutor, journalAbbreviationRepository, indexingTaskManager); this.entryTypesManager = entryTypesManager; setText(Localization.lang("Required fields")); diff --git a/src/main/java/org/jabref/gui/entryeditor/UserDefinedFieldsTab.java b/src/main/java/org/jabref/gui/entryeditor/UserDefinedFieldsTab.java index bc084a8e77b..aa4e65b48e3 100644 --- a/src/main/java/org/jabref/gui/entryeditor/UserDefinedFieldsTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/UserDefinedFieldsTab.java @@ -8,7 +8,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.SuggestionProviders; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.TaskExecutor; @@ -16,7 +15,6 @@ import org.jabref.logic.pdf.search.indexing.IndexingTaskManager; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.entry.field.Field; import org.jabref.preferences.PreferencesService; @@ -33,11 +31,9 @@ public UserDefinedFieldsTab(String name, StateManager stateManager, ThemeManager themeManager, IndexingTaskManager indexingTaskManager, - BibEntryTypesManager entryTypesManager, - ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, JournalAbbreviationRepository journalAbbreviationRepository) { - super(false, databaseContext, suggestionProviders, undoManager, dialogService, preferences, stateManager, themeManager, externalFileTypes, taskExecutor, journalAbbreviationRepository, indexingTaskManager); + super(false, databaseContext, suggestionProviders, undoManager, dialogService, preferences, stateManager, themeManager, taskExecutor, journalAbbreviationRepository, indexingTaskManager); this.fields = new LinkedHashSet<>(fields); diff --git a/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java b/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java index 6c51f8889dd..689d79dca69 100644 --- a/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java +++ b/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java @@ -9,7 +9,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.util.BindingsHelper; import org.jabref.gui.util.TaskExecutor; @@ -51,8 +50,7 @@ public void execute() { final AutoSetFileLinksUtil util = new AutoSetFileLinksUtil( database, preferences.getFilePreferences(), - preferences.getAutoLinkPreferences(), - ExternalFileTypes.getInstance()); + preferences.getAutoLinkPreferences()); final NamedCompound nc = new NamedCompound(Localization.lang("Automatically set file links")); Task linkFilesTask = new Task<>() { diff --git a/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java b/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java index e783ee0aed3..4d1f35e3b40 100644 --- a/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java +++ b/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java @@ -55,16 +55,16 @@ public List getFileExceptions() { private static final Logger LOGGER = LoggerFactory.getLogger(AutoSetFileLinksUtil.class); private final List directories; private final AutoLinkPreferences autoLinkPreferences; - private final ExternalFileTypes externalFileTypes; + private final FilePreferences filePreferences; - public AutoSetFileLinksUtil(BibDatabaseContext databaseContext, FilePreferences filePreferences, AutoLinkPreferences autoLinkPreferences, ExternalFileTypes externalFileTypes) { - this(databaseContext.getFileDirectories(filePreferences), autoLinkPreferences, externalFileTypes); + public AutoSetFileLinksUtil(BibDatabaseContext databaseContext, FilePreferences filePreferences, AutoLinkPreferences autoLinkPreferences) { + this(databaseContext.getFileDirectories(filePreferences), filePreferences, autoLinkPreferences); } - private AutoSetFileLinksUtil(List directories, AutoLinkPreferences autoLinkPreferences, ExternalFileTypes externalFileTypes) { + private AutoSetFileLinksUtil(List directories, FilePreferences filePreferences, AutoLinkPreferences autoLinkPreferences) { this.directories = directories; this.autoLinkPreferences = autoLinkPreferences; - this.externalFileTypes = externalFileTypes; + this.filePreferences = filePreferences; } public LinkFilesResult linkAssociatedFiles(List entries, NamedCompound ce) { @@ -107,7 +107,7 @@ public LinkFilesResult linkAssociatedFiles(List entries, NamedCompound public List findAssociatedNotLinkedFiles(BibEntry entry) throws IOException { List linkedFiles = new ArrayList<>(); - List extensions = externalFileTypes.getExternalFileTypeSelection().stream().map(ExternalFileType::getExtension).collect(Collectors.toList()); + List extensions = filePreferences.getExternalFileTypes().stream().map(ExternalFileType::getExtension).collect(Collectors.toList()); // Run the search operation FileFinder fileFinder = FileFinders.constructFromConfiguration(autoLinkPreferences); @@ -128,7 +128,7 @@ public List findAssociatedNotLinkedFiles(BibEntry entry) throws IOEx if (!fileAlreadyLinked) { Optional type = FileHelper.getFileExtension(foundFile) - .map(externalFileTypes::getExternalFileTypeByExt) + .map(extension -> ExternalFileTypes.getExternalFileTypeByExt(extension, filePreferences)) .orElse(Optional.of(new UnknownExternalFileType(""))); String strType = type.isPresent() ? type.get().getName() : ""; diff --git a/src/main/java/org/jabref/gui/externalfiles/DownloadFullTextAction.java b/src/main/java/org/jabref/gui/externalfiles/DownloadFullTextAction.java index 53be917cea1..be8b74ede44 100644 --- a/src/main/java/org/jabref/gui/externalfiles/DownloadFullTextAction.java +++ b/src/main/java/org/jabref/gui/externalfiles/DownloadFullTextAction.java @@ -14,7 +14,6 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.logic.importer.FulltextFetchers; import org.jabref.logic.l10n.Localization; @@ -146,8 +145,7 @@ private void addLinkedFileFromURL(BibDatabaseContext databaseContext, URL url, B databaseContext, Globals.TASK_EXECUTOR, dialogService, - preferences, - ExternalFileTypes.getInstance()); + preferences); onlineFile.download(); } else { diff --git a/src/main/java/org/jabref/gui/externalfiles/ExternalFilesEntryLinker.java b/src/main/java/org/jabref/gui/externalfiles/ExternalFilesEntryLinker.java index b62748a4959..7f9591c60f4 100644 --- a/src/main/java/org/jabref/gui/externalfiles/ExternalFilesEntryLinker.java +++ b/src/main/java/org/jabref/gui/externalfiles/ExternalFilesEntryLinker.java @@ -26,14 +26,12 @@ public class ExternalFilesEntryLinker { private static final Logger LOGGER = LoggerFactory.getLogger(ExternalFilesEntryLinker.class); - private final ExternalFileTypes externalFileTypes; private final FilePreferences filePreferences; private final BibDatabaseContext bibDatabaseContext; private final MoveFilesCleanup moveFilesCleanup; private final RenamePdfCleanup renameFilesCleanup; - public ExternalFilesEntryLinker(ExternalFileTypes externalFileTypes, FilePreferences filePreferences, BibDatabaseContext bibDatabaseContext) { - this.externalFileTypes = externalFileTypes; + public ExternalFilesEntryLinker(FilePreferences filePreferences, BibDatabaseContext bibDatabaseContext) { this.filePreferences = filePreferences; this.bibDatabaseContext = bibDatabaseContext; this.moveFilesCleanup = new MoveFilesCleanup(bibDatabaseContext, filePreferences); @@ -62,7 +60,7 @@ public void moveLinkedFilesToFileDir(BibEntry entry) { public void addFilesToEntry(BibEntry entry, List files) { for (Path file : files) { FileUtil.getFileExtension(file).ifPresent(ext -> { - ExternalFileType type = externalFileTypes.getExternalFileTypeByExt(ext) + ExternalFileType type = ExternalFileTypes.getExternalFileTypeByExt(ext, filePreferences) .orElse(new UnknownExternalFileType(ext)); Path relativePath = FileUtil.relativize(file, bibDatabaseContext.getFileDirectories(filePreferences)); LinkedFile linkedfile = new LinkedFile("", relativePath, type.getName()); diff --git a/src/main/java/org/jabref/gui/externalfiles/FileExtensionViewModel.java b/src/main/java/org/jabref/gui/externalfiles/FileExtensionViewModel.java index 121517bf5bc..6344babd905 100644 --- a/src/main/java/org/jabref/gui/externalfiles/FileExtensionViewModel.java +++ b/src/main/java/org/jabref/gui/externalfiles/FileExtensionViewModel.java @@ -11,17 +11,18 @@ import org.jabref.gui.util.FileFilterConverter; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.FileType; +import org.jabref.preferences.FilePreferences; public class FileExtensionViewModel { private final String description; private final List extensions; - private final ExternalFileTypes externalFileTypes; + private final FilePreferences filePreferences; - FileExtensionViewModel(FileType fileType, ExternalFileTypes externalFileTypes) { + FileExtensionViewModel(FileType fileType, FilePreferences filePreferences) { this.description = Localization.lang("%0 file", fileType.getName()); this.extensions = fileType.getExtensionsWithDot(); - this.externalFileTypes = externalFileTypes; + this.filePreferences = filePreferences; } public String getDescription() { @@ -29,7 +30,7 @@ public String getDescription() { } public JabRefIcon getIcon() { - return externalFileTypes.getExternalFileTypeByExt(extensions.get(0)) + return ExternalFileTypes.getExternalFileTypeByExt(extensions.get(0), filePreferences) .map(ExternalFileType::getIcon) .orElse(null); } diff --git a/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java b/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java index 61cc7afd2e8..f8ab4c2354c 100644 --- a/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java +++ b/src/main/java/org/jabref/gui/externalfiles/ImportHandler.java @@ -17,7 +17,6 @@ import org.jabref.gui.Globals; import org.jabref.gui.StateManager; import org.jabref.gui.duplicationFinder.DuplicateResolverDialog; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.undo.UndoableInsertEntries; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.DefaultTaskExecutor; @@ -65,7 +64,6 @@ public class ImportHandler { private final ImportFormatReader importFormatReader; public ImportHandler(BibDatabaseContext database, - ExternalFileTypes externalFileTypes, PreferencesService preferencesService, FileUpdateMonitor fileupdateMonitor, UndoManager undoManager, @@ -80,7 +78,7 @@ public ImportHandler(BibDatabaseContext database, this.dialogService = dialogService; this.importFormatReader = importFormatReader; - this.linker = new ExternalFilesEntryLinker(externalFileTypes, preferencesService.getFilePreferences(), database); + this.linker = new ExternalFilesEntryLinker(preferencesService.getFilePreferences(), database); this.contentImporter = new ExternalFilesContentImporter( preferencesService.getGeneralPreferences(), preferencesService.getImporterPreferences(), diff --git a/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogView.java b/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogView.java index 0805c8a1f22..9ccdfa8ec82 100644 --- a/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogView.java +++ b/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogView.java @@ -31,7 +31,6 @@ import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.actions.StandardActions; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.JabRefIcon; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.BaseDialog; @@ -108,7 +107,7 @@ public UnlinkedFilesDialogView() { @FXML private void initialize() { - viewModel = new UnlinkedFilesDialogViewModel(dialogService, ExternalFileTypes.getInstance(), undoManager, fileUpdateMonitor, preferencesService, stateManager, taskExecutor, importFormatReader); + viewModel = new UnlinkedFilesDialogViewModel(dialogService, undoManager, fileUpdateMonitor, preferencesService, stateManager, taskExecutor, importFormatReader); progressDisplay.progressProperty().bind(viewModel.progressValueProperty()); progressText.textProperty().bind(viewModel.progressTextProperty()); diff --git a/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogViewModel.java b/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogViewModel.java index fd942a61508..2129e473c4a 100644 --- a/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogViewModel.java +++ b/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogViewModel.java @@ -30,7 +30,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.FileDialogConfiguration; @@ -82,7 +81,6 @@ public class UnlinkedFilesDialogViewModel { private final FunctionBasedValidator scanDirectoryValidator; public UnlinkedFilesDialogViewModel(DialogService dialogService, - ExternalFileTypes externalFileTypes, UndoManager undoManager, FileUpdateMonitor fileUpdateMonitor, PreferencesService preferences, @@ -95,7 +93,6 @@ public UnlinkedFilesDialogViewModel(DialogService dialogService, this.bibDatabase = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); importHandler = new ImportHandler( bibDatabase, - externalFileTypes, preferences, fileUpdateMonitor, undoManager, @@ -104,9 +101,9 @@ public UnlinkedFilesDialogViewModel(DialogService dialogService, importFormatReader); this.fileFilterList = FXCollections.observableArrayList( - new FileExtensionViewModel(StandardFileType.ANY_FILE, externalFileTypes), - new FileExtensionViewModel(StandardFileType.BIBTEX_DB, externalFileTypes), - new FileExtensionViewModel(StandardFileType.PDF, externalFileTypes)); + new FileExtensionViewModel(StandardFileType.ANY_FILE, preferences.getFilePreferences()), + new FileExtensionViewModel(StandardFileType.BIBTEX_DB, preferences.getFilePreferences()), + new FileExtensionViewModel(StandardFileType.PDF, preferences.getFilePreferences())); this.dateFilterList = FXCollections.observableArrayList(DateRange.values()); diff --git a/src/main/java/org/jabref/gui/externalfiletype/ExternalFileType.java b/src/main/java/org/jabref/gui/externalfiletype/ExternalFileType.java index 15e4a869b51..0a5a44259cf 100644 --- a/src/main/java/org/jabref/gui/externalfiletype/ExternalFileType.java +++ b/src/main/java/org/jabref/gui/externalfiletype/ExternalFileType.java @@ -11,6 +11,10 @@ public interface ExternalFileType { String getMimeType(); + String getOpenWithApplication(); + + JabRefIcon getIcon(); + /** * Get the bibtex field name used for this file type. Currently we assume that field name equals filename extension. * @@ -20,7 +24,14 @@ default Field getField() { return FieldFactory.parseField(getExtension()); } - String getOpenWithApplication(); - - JabRefIcon getIcon(); + /** + * Return a String array representing this file type. This is used for storage into + * Preferences, and the same array can be used to construct the file type later, + * using the String[] constructor. + * + * @return A String[] containing all information about this file type. + */ + default String[] toStringArray() { + return new String[]{getName(), getExtension(), getMimeType(), getOpenWithApplication(), getIcon().name()}; + } } diff --git a/src/main/java/org/jabref/gui/externalfiletype/ExternalFileTypes.java b/src/main/java/org/jabref/gui/externalfiletype/ExternalFileTypes.java index 89209f2cffa..3cba8ebd4fa 100644 --- a/src/main/java/org/jabref/gui/externalfiletype/ExternalFileTypes.java +++ b/src/main/java/org/jabref/gui/externalfiletype/ExternalFileTypes.java @@ -3,18 +3,18 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Optional; import java.util.Set; -import java.util.TreeSet; -import org.jabref.gui.Globals; import org.jabref.logic.bibtex.FileFieldWriter; import org.jabref.model.entry.LinkedFile; import org.jabref.model.strings.StringUtil; import org.jabref.model.util.FileHelper; +import org.jabref.preferences.FilePreferences; // Do not make this class final, as it otherwise can't be mocked for tests public class ExternalFileTypes { @@ -22,40 +22,23 @@ public class ExternalFileTypes { // This String is used in the encoded list in prefs of external file type // modifications, in order to indicate a removed default file type: private static final String FILE_TYPE_REMOVED_FLAG = "REMOVED"; - // The only instance of this class: - private static ExternalFileTypes singleton; - // Map containing all registered external file types: - private final Set externalFileTypes = new TreeSet<>(Comparator.comparing(ExternalFileType::getName)); - - private final ExternalFileType HTML_FALLBACK_TYPE = StandardExternalFileType.URL; + private static final ExternalFileType HTML_FALLBACK_TYPE = StandardExternalFileType.URL; private ExternalFileTypes() { - updateExternalFileTypes(); - } - - public static ExternalFileTypes getInstance() { - if (ExternalFileTypes.singleton == null) { - ExternalFileTypes.singleton = new ExternalFileTypes(); - } - return ExternalFileTypes.singleton; } public static List getDefaultExternalFileTypes() { return Arrays.asList(StandardExternalFileType.values()); } - public Set getExternalFileTypeSelection() { - return externalFileTypes; - } - /** * Look up the external file type registered with this name, if any. * * @param name The file type name. * @return The ExternalFileType registered, or null if none. */ - public Optional getExternalFileTypeByName(String name) { - Optional externalFileType = externalFileTypes.stream().filter(type -> type.getName().equals(name)).findFirst(); + public static Optional getExternalFileTypeByName(String name, FilePreferences filePreferences) { + Optional externalFileType = filePreferences.getExternalFileTypes().stream().filter(type -> type.getName().equals(name)).findFirst(); if (externalFileType.isPresent()) { return externalFileType; } @@ -69,9 +52,9 @@ public Optional getExternalFileTypeByName(String name) { * @param extension The file extension. * @return The ExternalFileType registered, or null if none. */ - public Optional getExternalFileTypeByExt(String extension) { + public static Optional getExternalFileTypeByExt(String extension, FilePreferences filePreferences) { String extensionCleaned = extension.replace(".", "").replace("*", ""); - return externalFileTypes.stream().filter(type -> type.getExtension().equalsIgnoreCase(extensionCleaned)).findFirst(); + return filePreferences.getExternalFileTypes().stream().filter(type -> type.getExtension().equalsIgnoreCase(extensionCleaned)).findFirst(); } /** @@ -80,8 +63,8 @@ public Optional getExternalFileTypeByExt(String extension) { * @param extension The file extension. * @return true if an ExternalFileType with the extension exists, false otherwise */ - public boolean isExternalFileTypeByExt(String extension) { - return externalFileTypes.stream().anyMatch(type -> type.getExtension().equalsIgnoreCase(extension)); + public static boolean isExternalFileTypeByExt(String extension, FilePreferences filePreferences) { + return filePreferences.getExternalFileTypes().stream().anyMatch(type -> type.getExtension().equalsIgnoreCase(extension)); } /** @@ -90,10 +73,10 @@ public boolean isExternalFileTypeByExt(String extension) { * @param filename The name of the file whose type to look up. * @return The ExternalFileType registered, or null if none. */ - public Optional getExternalFileTypeForName(String filename) { + public static Optional getExternalFileTypeForName(String filename, FilePreferences filePreferences) { int longestFound = -1; ExternalFileType foundType = null; - for (ExternalFileType type : externalFileTypes) { + for (ExternalFileType type : filePreferences.getExternalFileTypes()) { if (!type.getExtension().isEmpty() && filename.toLowerCase(Locale.ROOT).endsWith(type.getExtension().toLowerCase(Locale.ROOT)) && (type.getExtension().length() > longestFound)) { longestFound = type.getExtension().length(); @@ -110,12 +93,12 @@ public Optional getExternalFileTypeForName(String filename) { * @return The ExternalFileType registered, or null if none. For the mime type "text/html", a valid file type is * guaranteed to be returned. */ - public Optional getExternalFileTypeByMimeType(String mimeType) { + public static Optional getExternalFileTypeByMimeType(String mimeType, FilePreferences filePreferences) { // Ignores parameters according to link: (https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) if (mimeType.indexOf(';') != -1) { mimeType = mimeType.substring(0, mimeType.indexOf(';')).trim(); } - for (ExternalFileType type : externalFileTypes) { + for (ExternalFileType type : filePreferences.getExternalFileTypes()) { if (type.getMimeType().equalsIgnoreCase(mimeType)) { return Optional.of(type); } @@ -127,21 +110,44 @@ public Optional getExternalFileTypeByMimeType(String mimeType) } } + public static Optional getExternalFileTypeByFile(Path file, FilePreferences filePreferences) { + final String filePath = file.toString(); + final Optional extension = FileHelper.getFileExtension(filePath); + return extension.flatMap(ext -> getExternalFileTypeByExt(ext, filePreferences)); + } + + public static Optional getExternalFileTypeByLinkedFile(LinkedFile linkedFile, boolean deduceUnknownType, FilePreferences filePreferences) { + Optional type = getExternalFileTypeByName(linkedFile.getFileType(), filePreferences); + boolean isUnknownType = type.isEmpty() || (type.get() instanceof UnknownExternalFileType); + + if (isUnknownType && deduceUnknownType) { + // No file type was recognized. Try to find a usable file type based on mime type: + Optional mimeType = getExternalFileTypeByMimeType(linkedFile.getFileType(), filePreferences); + if (mimeType.isPresent()) { + return mimeType; + } + + // No type could be found from mime type. Try based on the extension: + return FileHelper.getFileExtension(linkedFile.getLink()) + .flatMap(extension -> getExternalFileTypeByExt(extension, filePreferences)); + } else { + return type; + } + } + /** - * Reset the List of external file types after user customization. - * - * @param types The new List of external file types. This is the complete list, not just new entries. + * @return A StringList of customized and removed file types compared to the default list of external file types for storing */ - public void setExternalFileTypes(List types) { + public static String toStringList(Collection fileTypes) { // First find a list of the default types: List defTypes = new ArrayList<>(getDefaultExternalFileTypes()); // Make a list of types that are unchanged: List unchanged = new ArrayList<>(); + // Create a result list + List results = new ArrayList<>(); - externalFileTypes.clear(); - for (ExternalFileType type : types) { - externalFileTypes.add(type); - + for (ExternalFileType type : fileTypes) { + results.add(type); // See if we can find a type with matching name in the default type list: ExternalFileType found = null; for (ExternalFileType defType : defTypes) { @@ -166,52 +172,38 @@ public void setExternalFileTypes(List types) { // and from the list of defaults, since we don't need to mention these in prefs: for (ExternalFileType type : unchanged) { defTypes.remove(type); - types.remove(type); + results.remove(type); } // Now set up the array to write to prefs, containing all new types, all modified // types, and a flag denoting each default type that has been removed: - String[][] array = new String[types.size() + defTypes.size()][]; + String[][] array = new String[results.size() + defTypes.size()][]; int i = 0; - for (ExternalFileType type : types) { - array[i] = getStringArrayRepresentation(type); + for (ExternalFileType type : results) { + array[i] = type.toStringArray(); i++; } for (ExternalFileType type : defTypes) { array[i] = new String[] {type.getName(), FILE_TYPE_REMOVED_FLAG}; i++; } - Globals.prefs.storeExternalFileTypes(FileFieldWriter.encodeStringArray(array)); + return FileFieldWriter.encodeStringArray(array); } /** - * Return a String array representing this file type. This is used for storage into - * Preferences, and the same array can be used to construct the file type later, - * using the String[] constructor. - * - * @return A String[] containing all information about this file type. + * Set up the list of external file types, either from default values, or from values recorded in PreferencesService. */ - private String[] getStringArrayRepresentation(ExternalFileType type) { - return new String[] {type.getName(), type.getExtension(), type.getMimeType(), type.getOpenWithApplication(), type.getIcon().name()}; - } - - /** - * Set up the list of external file types, either from default values, or from values recorded in Preferences. - */ - private void updateExternalFileTypes() { + public static Set fromString(String storedFileTypes) { // First get a list of the default file types as a starting point: - List types = new ArrayList<>(getDefaultExternalFileTypes()); + Set types = new HashSet<>(getDefaultExternalFileTypes()); + // If no changes have been stored, simply use the defaults: - Optional storedFileTypes = Globals.prefs.getExternalFileTypes(); - if (storedFileTypes.isEmpty()) { - externalFileTypes.clear(); - externalFileTypes.addAll(types); - return; + if (StringUtil.isBlank(storedFileTypes)) { + return types; } // Read the prefs information for file types: - String[][] vals = StringUtil - .decodeStringDoubleArray(storedFileTypes.orElse("")); + String[][] vals = StringUtil.decodeStringDoubleArray(storedFileTypes); for (String[] val : vals) { if ((val.length == 2) && val[1].equals(FILE_TYPE_REMOVED_FLAG)) { // This entry indicates that a default entry type should be removed: @@ -248,32 +240,6 @@ private void updateExternalFileTypes() { } } - // Finally, build the list of types based on the modified defaults list: - externalFileTypes.addAll(types); - } - - public Optional getExternalFileTypeByFile(Path file) { - final String filePath = file.toString(); - final Optional extension = FileHelper.getFileExtension(filePath); - return extension.flatMap(this::getExternalFileTypeByExt); - } - - public Optional fromLinkedFile(LinkedFile linkedFile, boolean deduceUnknownType) { - Optional type = getExternalFileTypeByName(linkedFile.getFileType()); - boolean isUnknownType = type.isEmpty() || (type.get() instanceof UnknownExternalFileType); - - if (isUnknownType && deduceUnknownType) { - // No file type was recognized. Try to find a usable file type based on mime type: - Optional mimeType = getExternalFileTypeByMimeType(linkedFile.getFileType()); - if (mimeType.isPresent()) { - return mimeType; - } - - // No type could be found from mime type. Try based on the extension: - return FileHelper.getFileExtension(linkedFile.getLink()) - .flatMap(this::getExternalFileTypeByExt); - } else { - return type; - } + return types; } } diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index 89a943d9e1f..b2f9e1749d7 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -82,7 +82,6 @@ public class LinkedFileViewModel extends AbstractViewModel { private final TaskExecutor taskExecutor; private final PreferencesService preferences; private final LinkedFileHandler linkedFileHandler; - private final ExternalFileTypes externalFileTypes; private final Validator fileExistsValidator; @@ -91,8 +90,7 @@ public LinkedFileViewModel(LinkedFile linkedFile, BibDatabaseContext databaseContext, TaskExecutor taskExecutor, DialogService dialogService, - PreferencesService preferences, - ExternalFileTypes externalFileTypes) { + PreferencesService preferences) { this.linkedFile = linkedFile; this.preferences = preferences; @@ -101,7 +99,6 @@ public LinkedFileViewModel(LinkedFile linkedFile, this.entry = entry; this.dialogService = dialogService; this.taskExecutor = taskExecutor; - this.externalFileTypes = externalFileTypes; fileExistsValidator = new FunctionBasedValidator<>( linkedFile.linkProperty(), @@ -176,7 +173,7 @@ public Optional findIn(List directories) { } public JabRefIcon getTypeIcon() { - return externalFileTypes.fromLinkedFile(linkedFile, false) + return ExternalFileTypes.getExternalFileTypeByLinkedFile(linkedFile, false, preferences.getFilePreferences()) .map(ExternalFileType::getIcon) .orElse(IconTheme.JabRefIcons.FILE); } @@ -199,7 +196,7 @@ public Observable[] getObservables() { public void open() { try { - Optional type = ExternalFileTypes.getInstance().fromLinkedFile(linkedFile, true); + Optional type = ExternalFileTypes.getExternalFileTypeByLinkedFile(linkedFile, true, preferences.getFilePreferences()); boolean successful = JabRefDesktop.openExternalFileAnyFormat(databaseContext, preferences, linkedFile.getLink(), type); if (!successful) { dialogService.showErrorDialogAndWait(Localization.lang("File not found"), Localization.lang("Could not find file '%0'.", linkedFile.getLink())); @@ -444,7 +441,10 @@ public void download() { } if (!isDuplicate) { - LinkedFile newLinkedFile = LinkedFilesEditorViewModel.fromFile(destination, databaseContext.getFileDirectories(preferences.getFilePreferences()), externalFileTypes); + LinkedFile newLinkedFile = LinkedFilesEditorViewModel.fromFile( + destination, + databaseContext.getFileDirectories(preferences.getFilePreferences()), + preferences.getFilePreferences()); List linkedFiles = entry.getFiles(); entry.addLinkedFile(entry, linkedFile, newLinkedFile, linkedFiles); @@ -523,15 +523,15 @@ private Optional inferFileTypeFromMimeType(URLDownload urlDown if (mimeType != null) { LOGGER.debug("MIME Type suggested: " + mimeType); - return externalFileTypes.getExternalFileTypeByMimeType(mimeType); + return ExternalFileTypes.getExternalFileTypeByMimeType(mimeType, preferences.getFilePreferences()); } else { return Optional.empty(); } } private Optional inferFileTypeFromURL(String url) { - return URLUtil.getSuffix(url) - .flatMap(externalFileTypes::getExternalFileTypeByExt); + return URLUtil.getSuffix(url, preferences.getFilePreferences()) + .flatMap(extension -> ExternalFileTypes.getExternalFileTypeByExt(extension, preferences.getFilePreferences())); } public LinkedFile getFile() { diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java index 4525c7f050c..44a3f15d538 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java @@ -38,6 +38,7 @@ import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.Field; import org.jabref.model.util.FileHelper; +import org.jabref.preferences.FilePreferences; import org.jabref.preferences.PreferencesService; public class LinkedFilesEditorViewModel extends AbstractEditorViewModel { @@ -48,7 +49,6 @@ public class LinkedFilesEditorViewModel extends AbstractEditorViewModel { private final BibDatabaseContext databaseContext; private final TaskExecutor taskExecutor; private final PreferencesService preferences; - private final ExternalFileTypes externalFileTypes = ExternalFileTypes.getInstance(); public LinkedFilesEditorViewModel(Field field, SuggestionProvider suggestionProvider, DialogService dialogService, @@ -87,27 +87,25 @@ private static String getStringRepresentation(List files) { * * TODO: Move this method to {@link LinkedFile} as soon as {@link CustomExternalFileType} lives in model. */ - public static LinkedFile fromFile(Path file, List fileDirectories, ExternalFileTypes externalFileTypesFile) { + public static LinkedFile fromFile(Path file, List fileDirectories, FilePreferences filePreferences) { String fileExtension = FileHelper.getFileExtension(file).orElse(""); - ExternalFileType suggestedFileType = externalFileTypesFile - .getExternalFileTypeByExt(fileExtension) - .orElse(new UnknownExternalFileType(fileExtension)); + ExternalFileType suggestedFileType = ExternalFileTypes.getExternalFileTypeByExt(fileExtension, filePreferences) + .orElse(new UnknownExternalFileType(fileExtension)); Path relativePath = FileUtil.relativize(file, fileDirectories); return new LinkedFile("", relativePath, suggestedFileType.getName()); } - public LinkedFileViewModel fromFile(Path file) { + public LinkedFileViewModel fromFile(Path file, FilePreferences filePreferences) { List fileDirectories = databaseContext.getFileDirectories(preferences.getFilePreferences()); - LinkedFile linkedFile = fromFile(file, fileDirectories, externalFileTypes); + LinkedFile linkedFile = fromFile(file, fileDirectories, filePreferences); return new LinkedFileViewModel( linkedFile, entry, databaseContext, taskExecutor, dialogService, - preferences, - externalFileTypes); + preferences); } public boolean isFulltextLookupInProgress() { @@ -122,8 +120,7 @@ private List parseToFileViewModel(String stringValue) { databaseContext, taskExecutor, dialogService, - preferences, - externalFileTypes)) + preferences)) .collect(Collectors.toList()); } @@ -145,15 +142,14 @@ public void addNewFile() { List fileDirectories = databaseContext.getFileDirectories(preferences.getFilePreferences()); dialogService.showFileOpenDialogAndGetMultipleFiles(fileDialogConfiguration).forEach(newFile -> { - LinkedFile newLinkedFile = fromFile(newFile, fileDirectories, externalFileTypes); + LinkedFile newLinkedFile = fromFile(newFile, fileDirectories, preferences.getFilePreferences()); files.add(new LinkedFileViewModel( newLinkedFile, entry, databaseContext, taskExecutor, dialogService, - preferences, - externalFileTypes)); + preferences)); }); } @@ -178,8 +174,7 @@ private List findAssociatedNotLinkedFiles(BibEntry entry) { AutoSetFileLinksUtil util = new AutoSetFileLinksUtil( databaseContext, preferences.getFilePreferences(), - preferences.getAutoLinkPreferences(), - ExternalFileTypes.getInstance()); + preferences.getAutoLinkPreferences()); try { List linkedFiles = util.findAssociatedNotLinkedFiles(entry); for (LinkedFile linkedFile : linkedFiles) { @@ -189,8 +184,7 @@ private List findAssociatedNotLinkedFiles(BibEntry entry) { databaseContext, taskExecutor, dialogService, - preferences, - externalFileTypes); + preferences); newLinkedFile.markAsAutomaticallyFound(); result.add(newLinkedFile); } @@ -241,8 +235,7 @@ private void addFromURL(URL url) { databaseContext, taskExecutor, dialogService, - preferences, - externalFileTypes); + preferences); files.add(onlineFile); onlineFile.download(); } diff --git a/src/main/java/org/jabref/gui/fieldeditors/URLUtil.java b/src/main/java/org/jabref/gui/fieldeditors/URLUtil.java index 1ee8e8b2652..d7f58db7c00 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/URLUtil.java +++ b/src/main/java/org/jabref/gui/fieldeditors/URLUtil.java @@ -8,6 +8,7 @@ import java.util.Optional; import org.jabref.gui.externalfiletype.ExternalFileTypes; +import org.jabref.preferences.FilePreferences; public class URLUtil { private static final String URL_EXP = "^(https?|ftp)://.+"; @@ -90,7 +91,7 @@ public static boolean isURL(String url) { * @param link The link * @return The suffix, excluding the dot (e.g. "pdf") */ - public static Optional getSuffix(final String link) { + public static Optional getSuffix(final String link, FilePreferences filePreferences) { String strippedLink = link; try { // Try to strip the query string, if any, to get the correct suffix: @@ -110,7 +111,7 @@ public static Optional getSuffix(final String link) { } else { suffix = strippedLink.substring(strippedLinkIndex + 1); } - if (!ExternalFileTypes.getInstance().isExternalFileTypeByExt(suffix)) { + if (!ExternalFileTypes.isExternalFileTypeByExt(suffix, filePreferences)) { // If the suffix doesn't seem to give any reasonable file type, try // with the non-stripped link: int index = link.lastIndexOf('.'); diff --git a/src/main/java/org/jabref/gui/importer/GenerateEntryFromIdAction.java b/src/main/java/org/jabref/gui/importer/GenerateEntryFromIdAction.java index 619ec5a8e35..95e2eb99d53 100644 --- a/src/main/java/org/jabref/gui/importer/GenerateEntryFromIdAction.java +++ b/src/main/java/org/jabref/gui/importer/GenerateEntryFromIdAction.java @@ -8,7 +8,6 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.externalfiles.ImportHandler; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.importer.CompositeIdFetcher; @@ -32,7 +31,13 @@ public class GenerateEntryFromIdAction extends SimpleCommand { private final PopOver entryFromIdPopOver; private final StateManager stateManager; - public GenerateEntryFromIdAction(LibraryTab libraryTab, DialogService dialogService, PreferencesService preferencesService, TaskExecutor taskExecutor, PopOver entryFromIdPopOver, String identifier, StateManager stateManager) { + public GenerateEntryFromIdAction(LibraryTab libraryTab, + DialogService dialogService, + PreferencesService preferencesService, + TaskExecutor taskExecutor, + PopOver entryFromIdPopOver, + String identifier, + StateManager stateManager) { this.libraryTab = libraryTab; this.dialogService = dialogService; this.preferencesService = preferencesService; @@ -69,7 +74,7 @@ public void execute() { Optional result = bibEntry; if (result.isPresent()) { final BibEntry entry = result.get(); - ImportHandler handler = new ImportHandler(libraryTab.getBibDatabaseContext(), ExternalFileTypes.getInstance(), preferencesService, Globals.getFileUpdateMonitor(), libraryTab.getUndoManager(), stateManager, dialogService, null); + ImportHandler handler = new ImportHandler(libraryTab.getBibDatabaseContext(), preferencesService, Globals.getFileUpdateMonitor(), libraryTab.getUndoManager(), stateManager, dialogService, null); handler.importEntryWithDuplicateCheck(libraryTab.getBibDatabaseContext(), entry); } else { dialogService.notify("No entry found or import canceled"); diff --git a/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java b/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java index 877a677234c..0f75519e910 100644 --- a/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java +++ b/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java @@ -17,7 +17,6 @@ import org.jabref.gui.StateManager; import org.jabref.gui.duplicationFinder.DuplicateResolverDialog; import org.jabref.gui.externalfiles.ImportHandler; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.TaskExecutor; @@ -149,8 +148,7 @@ public void importEntries(List entriesToImport, boolean shouldDownload databaseContext, taskExecutor, dialogService, - preferences, - ExternalFileTypes.getInstance()).download()); + preferences).download()); } } @@ -166,7 +164,6 @@ public void importEntries(List entriesToImport, boolean shouldDownload private void buildImportHandlerThenImportEntries(List entriesToImport) { ImportHandler importHandler = new ImportHandler( databaseContext, - ExternalFileTypes.getInstance(), preferences, fileUpdateMonitor, undoManager, diff --git a/src/main/java/org/jabref/gui/linkedfile/AttachFileAction.java b/src/main/java/org/jabref/gui/linkedfile/AttachFileAction.java index 00e0c1f3b4b..8dad9f0399c 100644 --- a/src/main/java/org/jabref/gui/linkedfile/AttachFileAction.java +++ b/src/main/java/org/jabref/gui/linkedfile/AttachFileAction.java @@ -8,7 +8,6 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFilesEditorViewModel; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.util.FileDialogConfiguration; @@ -62,9 +61,10 @@ public void execute() { .build(); dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(newFile -> { - LinkedFile linkedFile = LinkedFilesEditorViewModel.fromFile(newFile, + LinkedFile linkedFile = LinkedFilesEditorViewModel.fromFile( + newFile, databaseContext.getFileDirectories(filePreferences), - ExternalFileTypes.getInstance()); + filePreferences); LinkedFileEditDialogView dialog = new LinkedFileEditDialogView(linkedFile); diff --git a/src/main/java/org/jabref/gui/linkedfile/LinkedFileEditDialogView.java b/src/main/java/org/jabref/gui/linkedfile/LinkedFileEditDialogView.java index f8ad3e1f7bc..6ed39ce1ae9 100644 --- a/src/main/java/org/jabref/gui/linkedfile/LinkedFileEditDialogView.java +++ b/src/main/java/org/jabref/gui/linkedfile/LinkedFileEditDialogView.java @@ -11,7 +11,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.externalfiletype.ExternalFileType; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.util.BaseDialog; import org.jabref.model.entry.LinkedFile; import org.jabref.preferences.PreferencesService; @@ -32,12 +31,10 @@ public class LinkedFileEditDialogView extends BaseDialog { private LinkedFilesEditDialogViewModel viewModel; private final LinkedFile linkedFile; - private final ExternalFileTypes externalFileTypes; public LinkedFileEditDialogView(LinkedFile linkedFile) { this.linkedFile = linkedFile; - this.externalFileTypes = ExternalFileTypes.getInstance(); ViewLoader.view(this) .load() .setAsContent(this.getDialogPane()); @@ -55,7 +52,7 @@ public LinkedFileEditDialogView(LinkedFile linkedFile) { @FXML private void initialize() { - viewModel = new LinkedFilesEditDialogViewModel(linkedFile, stateManager.getActiveDatabase().get(), dialogService, preferences.getFilePreferences(), externalFileTypes); + viewModel = new LinkedFilesEditDialogViewModel(linkedFile, stateManager.getActiveDatabase().get(), dialogService, preferences.getFilePreferences()); fileType.itemsProperty().bindBidirectional(viewModel.externalFileTypeProperty()); description.textProperty().bindBidirectional(viewModel.descriptionProperty()); link.textProperty().bindBidirectional(viewModel.linkProperty()); diff --git a/src/main/java/org/jabref/gui/linkedfile/LinkedFilesEditDialogViewModel.java b/src/main/java/org/jabref/gui/linkedfile/LinkedFilesEditDialogViewModel.java index 12d3f3f45ce..a46e908c358 100644 --- a/src/main/java/org/jabref/gui/linkedfile/LinkedFilesEditDialogViewModel.java +++ b/src/main/java/org/jabref/gui/linkedfile/LinkedFilesEditDialogViewModel.java @@ -41,14 +41,15 @@ public class LinkedFilesEditDialogViewModel extends AbstractViewModel { private final BibDatabaseContext database; private final DialogService dialogService; private final FilePreferences filePreferences; - private final ExternalFileTypes externalFileTypes; - public LinkedFilesEditDialogViewModel(LinkedFile linkedFile, BibDatabaseContext database, DialogService dialogService, FilePreferences filePreferences, ExternalFileTypes externalFileTypes) { + public LinkedFilesEditDialogViewModel(LinkedFile linkedFile, + BibDatabaseContext database, + DialogService dialogService, + FilePreferences filePreferences) { this.database = database; this.dialogService = dialogService; this.filePreferences = filePreferences; - this.externalFileTypes = externalFileTypes; - allExternalFileTypes.set(FXCollections.observableArrayList(externalFileTypes.getExternalFileTypeSelection())); + allExternalFileTypes.set(FXCollections.observableArrayList(filePreferences.getExternalFileTypes())); monadicSelectedExternalFileType = EasyBind.wrapNullable(selectedExternalFileType); setValues(linkedFile); @@ -58,12 +59,14 @@ private void setExternalFileTypeByExtension(String link) { if (!link.isEmpty()) { // Check if this looks like a remote link: if (REMOTE_LINK_PATTERN.matcher(link).matches()) { - externalFileTypes.getExternalFileTypeByExt("html").ifPresent(selectedExternalFileType::setValue); + ExternalFileTypes.getExternalFileTypeByExt("html", filePreferences) + .ifPresent(selectedExternalFileType::setValue); } // Try to guess the file type: String theLink = link.trim(); - externalFileTypes.getExternalFileTypeForName(theLink).ifPresent(selectedExternalFileType::setValue); + ExternalFileTypes.getExternalFileTypeForName(theLink, filePreferences) + .ifPresent(selectedExternalFileType::setValue); } } @@ -101,7 +104,7 @@ public void setValues(LinkedFile linkedFile) { selectedExternalFileType.setValue(null); // See what is a reasonable selection for the type combobox: - Optional fileType = externalFileTypes.fromLinkedFile(linkedFile, false); + Optional fileType = ExternalFileTypes.getExternalFileTypeByLinkedFile(linkedFile, false, filePreferences); if (fileType.isPresent() && !(fileType.get() instanceof UnknownExternalFileType)) { selectedExternalFileType.setValue(fileType.get()); } else if ((linkedFile.getLink() != null) && (!linkedFile.getLink().isEmpty())) { diff --git a/src/main/java/org/jabref/gui/maintable/CellFactory.java b/src/main/java/org/jabref/gui/maintable/CellFactory.java index 9f0940831d4..13c65f6a336 100644 --- a/src/main/java/org/jabref/gui/maintable/CellFactory.java +++ b/src/main/java/org/jabref/gui/maintable/CellFactory.java @@ -8,7 +8,6 @@ import javafx.scene.Node; import org.jabref.gui.externalfiletype.ExternalFileType; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.icon.JabRefIcon; import org.jabref.gui.specialfields.SpecialFieldViewModel; @@ -22,7 +21,7 @@ public class CellFactory { private final Map TABLE_ICONS = new HashMap<>(); - public CellFactory(ExternalFileTypes externalFileTypes, PreferencesService preferencesService, UndoManager undoManager) { + public CellFactory(PreferencesService preferencesService, UndoManager undoManager) { JabRefIcon icon; icon = IconTheme.JabRefIcons.PDF_FILE; // icon.setToo(Localization.lang("Open") + " PDF"); @@ -56,7 +55,7 @@ public CellFactory(ExternalFileTypes externalFileTypes, PreferencesService prefe // icon.setToolTipText(Localization.lang("Open file")); TABLE_ICONS.put(StandardField.FILE, icon); - for (ExternalFileType fileType : externalFileTypes.getExternalFileTypeSelection()) { + for (ExternalFileType fileType : preferencesService.getFilePreferences().getExternalFileTypes()) { icon = fileType.getIcon(); // icon.setToolTipText(Localization.lang("Open %0 file", fileType.getName())); TABLE_ICONS.put(fileType.getField(), icon); diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index d37f3bb09c4..8f7fff99355 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -34,7 +34,6 @@ import org.jabref.gui.actions.StandardActions; import org.jabref.gui.edit.EditAction; import org.jabref.gui.externalfiles.ImportHandler; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.keyboard.KeyBindingRepository; import org.jabref.gui.maintable.columns.LibraryColumn; @@ -79,7 +78,6 @@ public MainTable(MainTableDataModel model, PreferencesService preferencesService, DialogService dialogService, StateManager stateManager, - ExternalFileTypes externalFileTypes, KeyBindingRepository keyBindingRepository, ClipBoardManager clipBoardManager, ImportFormatReader importFormatReader) { @@ -95,7 +93,7 @@ public MainTable(MainTableDataModel model, MainTablePreferences mainTablePreferences = preferencesService.getMainTablePreferences(); importHandler = new ImportHandler( - database, externalFileTypes, + database, preferencesService, Globals.getFileUpdateMonitor(), undoManager, @@ -113,7 +111,6 @@ public MainTable(MainTableDataModel model, database, preferencesService, preferencesService.getColumnPreferences(), - externalFileTypes, libraryTab.getUndoManager(), dialogService, stateManager).createColumns()); diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index ece234f9ff4..52cf6a2f04f 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -23,7 +23,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.maintable.columns.FieldColumn; import org.jabref.gui.maintable.columns.FileColumn; @@ -54,7 +53,6 @@ public class MainTableColumnFactory { private final PreferencesService preferencesService; private final ColumnPreferences columnPreferences; - private final ExternalFileTypes externalFileTypes; private final BibDatabaseContext database; private final CellFactory cellFactory; private final UndoManager undoManager; @@ -64,16 +62,14 @@ public class MainTableColumnFactory { public MainTableColumnFactory(BibDatabaseContext database, PreferencesService preferencesService, ColumnPreferences abstractColumnPrefs, - ExternalFileTypes externalFileTypes, UndoManager undoManager, DialogService dialogService, StateManager stateManager) { this.database = Objects.requireNonNull(database); this.preferencesService = Objects.requireNonNull(preferencesService); this.columnPreferences = abstractColumnPrefs; - this.externalFileTypes = Objects.requireNonNull(externalFileTypes); this.dialogService = dialogService; - this.cellFactory = new CellFactory(externalFileTypes, preferencesService, undoManager); + this.cellFactory = new CellFactory(preferencesService, undoManager); this.undoManager = undoManager; this.stateManager = stateManager; } @@ -233,7 +229,6 @@ private TableColumn private TableColumn> createFilesColumn(MainTableColumnModel columnModel) { return new FileColumn(columnModel, database, - externalFileTypes, dialogService, preferencesService); } @@ -244,7 +239,6 @@ private TableColumn> createFilesColumn( private TableColumn> createExtraFileColumn(MainTableColumnModel columnModel) { return new FileColumn(columnModel, database, - externalFileTypes, dialogService, preferencesService, columnModel.getQualifier()); diff --git a/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java b/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java index 9f669a18431..499f07a3526 100644 --- a/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java +++ b/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java @@ -8,7 +8,6 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; @@ -68,8 +67,7 @@ public void execute() { databaseContext, Globals.TASK_EXECUTOR, dialogService, - preferencesService, - ExternalFileTypes.getInstance()); + preferencesService); linkedFileViewModelList.add(linkedFileViewModel); } @@ -93,8 +91,7 @@ public void execute() { databaseContext, Globals.TASK_EXECUTOR, dialogService, - preferencesService, - ExternalFileTypes.getInstance()); + preferencesService); linkedFileViewModel.open(); } }); diff --git a/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java b/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java index 8ce16f62f1b..92c8404ca39 100644 --- a/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java +++ b/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java @@ -5,7 +5,6 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; @@ -49,9 +48,7 @@ public void execute() { databaseContext, Globals.TASK_EXECUTOR, dialogService, - preferencesService, - ExternalFileTypes.getInstance() - ); + preferencesService); linkedFileViewModel.openFolder(); }); } else { @@ -61,9 +58,7 @@ public void execute() { databaseContext, Globals.TASK_EXECUTOR, dialogService, - preferencesService, - ExternalFileTypes.getInstance() - ); + preferencesService); linkedFileViewModel.openFolder(); } }); diff --git a/src/main/java/org/jabref/gui/maintable/columns/FileColumn.java b/src/main/java/org/jabref/gui/maintable/columns/FileColumn.java index c325637af32..5aaeeb207a0 100644 --- a/src/main/java/org/jabref/gui/maintable/columns/FileColumn.java +++ b/src/main/java/org/jabref/gui/maintable/columns/FileColumn.java @@ -32,7 +32,6 @@ */ public class FileColumn extends MainTableColumn> { - private final ExternalFileTypes externalFileTypes; private final DialogService dialogService; private final BibDatabaseContext database; private final PreferencesService preferencesService; @@ -42,11 +41,9 @@ public class FileColumn extends MainTableColumn> { */ public FileColumn(MainTableColumnModel model, BibDatabaseContext database, - ExternalFileTypes externalFileTypes, DialogService dialogService, PreferencesService preferencesService) { super(model); - this.externalFileTypes = Objects.requireNonNull(externalFileTypes); this.database = Objects.requireNonNull(database); this.dialogService = dialogService; this.preferencesService = preferencesService; @@ -68,8 +65,7 @@ public FileColumn(MainTableColumnModel model, entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, - preferencesService, - externalFileTypes); + preferencesService); linkedFileViewModel.open(); } }) @@ -81,22 +77,19 @@ public FileColumn(MainTableColumnModel model, */ public FileColumn(MainTableColumnModel model, BibDatabaseContext database, - ExternalFileTypes externalFileTypes, DialogService dialogService, PreferencesService preferencesService, String fileType) { super(model); - this.externalFileTypes = Objects.requireNonNull(externalFileTypes); this.database = Objects.requireNonNull(database); this.dialogService = dialogService; this.preferencesService = preferencesService; setCommonSettings(); - this.setGraphic(externalFileTypes - .getExternalFileTypeByName(fileType) - .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) - .getGraphicNode()); + this.setGraphic(ExternalFileTypes.getExternalFileTypeByName(fileType, preferencesService.getFilePreferences()) + .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) + .getGraphicNode()); new ValueTableCellFactory>() .withGraphic(linkedFiles -> createFileIcon(linkedFiles.stream().filter(linkedFile -> @@ -131,8 +124,7 @@ private ContextMenu createFileMenu(BibEntryTableViewModel entry, List linkedFiles) { if (linkedFiles.size() > 1) { return IconTheme.JabRefIcons.FILE_MULTIPLE.getGraphicNode(); } else if (linkedFiles.size() == 1) { - return externalFileTypes.fromLinkedFile(linkedFiles.get(0), true) + return ExternalFileTypes.getExternalFileTypeByLinkedFile(linkedFiles.get(0), true, preferencesService.getFilePreferences()) .map(ExternalFileType::getIcon) .orElse(IconTheme.JabRefIcons.FILE) .getGraphicNode(); diff --git a/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java b/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java index 92bd6dd607f..b78e69aeba9 100644 --- a/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java +++ b/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java @@ -93,7 +93,7 @@ public void deleteStyle() { public void editStyle() { OOBibStyle style = selectedItem.getValue().getStyle(); - Optional type = ExternalFileTypes.getInstance().getExternalFileTypeByExt("jstyle"); + Optional type = ExternalFileTypes.getExternalFileTypeByExt("jstyle", preferencesService.getFilePreferences()); try { JabRefDesktop.openExternalFileAnyFormat(new BibDatabaseContext(), preferencesService, style.getPath(), type); } catch (IOException e) { diff --git a/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTab.java b/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTab.java index 41998975660..0347047dee9 100644 --- a/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTab.java +++ b/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTab.java @@ -5,7 +5,6 @@ import javafx.scene.control.TableView; import org.jabref.gui.externalfiletype.ExternalFileType; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.icon.JabRefIcon; import org.jabref.gui.preferences.AbstractPreferenceTabView; @@ -43,7 +42,7 @@ public String getTabName() { @FXML public void initialize() { - viewModel = new ExternalFileTypesTabViewModel(ExternalFileTypes.getInstance()); + viewModel = new ExternalFileTypesTabViewModel(preferencesService.getFilePreferences()); fileTypesTable.setItems(viewModel.getFileTypes()); diff --git a/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTabViewModel.java b/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTabViewModel.java index ee669177d6d..e1ff1973bcb 100644 --- a/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTabViewModel.java @@ -14,26 +14,28 @@ import org.jabref.gui.icon.IconTheme; import org.jabref.gui.preferences.PreferenceTabViewModel; import org.jabref.logic.l10n.Localization; +import org.jabref.preferences.FilePreferences; import com.airhacks.afterburner.injection.Injector; public class ExternalFileTypesTabViewModel implements PreferenceTabViewModel { - private final ExternalFileTypes externalFileTypes; + private final FilePreferences filePreferences; private final ObservableList fileTypes = FXCollections.observableArrayList(); - public ExternalFileTypesTabViewModel(ExternalFileTypes externalFileTypes) { - this.externalFileTypes = externalFileTypes; + public ExternalFileTypesTabViewModel(FilePreferences filePreferences) { + this.filePreferences = filePreferences; } @Override public void setValues() { - fileTypes.setAll(externalFileTypes.getExternalFileTypeSelection()); + fileTypes.setAll(filePreferences.getExternalFileTypes()); fileTypes.sort(Comparator.comparing(ExternalFileType::getName)); } public void storeSettings() { - externalFileTypes.setExternalFileTypes(fileTypes); + filePreferences.getExternalFileTypes().clear(); + filePreferences.getExternalFileTypes().addAll(fileTypes); } public void resetToDefaults() { diff --git a/src/main/java/org/jabref/gui/preferences/protectedterms/ProtectedTermsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/protectedterms/ProtectedTermsTabViewModel.java index ca6b668ab5d..62c09375df6 100644 --- a/src/main/java/org/jabref/gui/preferences/protectedterms/ProtectedTermsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/protectedterms/ProtectedTermsTabViewModel.java @@ -125,8 +125,8 @@ public void createNewFile() { public void edit(ProtectedTermsListItemModel file) { Optional termsFileType = OptionalUtil.orElse( - ExternalFileTypes.getInstance().getExternalFileTypeByExt("terms"), - ExternalFileTypes.getInstance().getExternalFileTypeByExt("txt") + ExternalFileTypes.getExternalFileTypeByExt("terms", preferences.getFilePreferences()), + ExternalFileTypes.getExternalFileTypeByExt("txt", preferences.getFilePreferences()) ); String fileName = file.getTermsList().getLocation(); diff --git a/src/main/java/org/jabref/gui/preferences/table/TableTabViewModel.java b/src/main/java/org/jabref/gui/preferences/table/TableTabViewModel.java index 2184469c933..ecae4a7d091 100644 --- a/src/main/java/org/jabref/gui/preferences/table/TableTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/table/TableTabViewModel.java @@ -14,7 +14,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.externalfiletype.ExternalFileType; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.maintable.ColumnPreferences; import org.jabref.gui.maintable.MainTableColumnModel; import org.jabref.gui.maintable.MainTableNameFormatPreferences; @@ -180,10 +179,10 @@ private void removeSpecialFieldColumns() { } private void insertExtraFileColumns() { - ExternalFileTypes.getInstance().getExternalFileTypeSelection().stream() - .map(ExternalFileType::getName) - .map(name -> new MainTableColumnModel(MainTableColumnModel.Type.EXTRAFILE, name)) - .forEach(item -> availableColumnsProperty.getValue().add(item)); + preferences.getFilePreferences().getExternalFileTypes().stream() + .map(ExternalFileType::getName) + .map(name -> new MainTableColumnModel(MainTableColumnModel.Type.EXTRAFILE, name)) + .forEach(item -> availableColumnsProperty.getValue().add(item)); } private void removeExtraFileColumns() { diff --git a/src/main/java/org/jabref/gui/preview/PreviewPanel.java b/src/main/java/org/jabref/gui/preview/PreviewPanel.java index f16b27d8b13..94cf57cd1e3 100644 --- a/src/main/java/org/jabref/gui/preview/PreviewPanel.java +++ b/src/main/java/org/jabref/gui/preview/PreviewPanel.java @@ -19,7 +19,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.externalfiles.ExternalFilesEntryLinker; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.keyboard.KeyBindingRepository; @@ -50,7 +49,6 @@ public class PreviewPanel extends VBox { public PreviewPanel(BibDatabaseContext database, DialogService dialogService, - ExternalFileTypes externalFileTypes, KeyBindingRepository keyBindingRepository, PreferencesService preferences, StateManager stateManager, @@ -61,7 +59,7 @@ public PreviewPanel(BibDatabaseContext database, this.stateManager = stateManager; this.previewPreferences = preferences.getPreviewPreferences(); this.indexingTaskManager = indexingTaskManager; - this.fileLinker = new ExternalFilesEntryLinker(externalFileTypes, preferences.getFilePreferences(), database); + this.fileLinker = new ExternalFilesEntryLinker(preferences.getFilePreferences(), database); PreviewPreferences previewPreferences = preferences.getPreviewPreferences(); previewView = new PreviewViewer(database, dialogService, stateManager, themeManager); diff --git a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java index d6b3bfc0364..d42bcd34cb7 100644 --- a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java +++ b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java @@ -47,7 +47,6 @@ import org.jabref.gui.autocompleter.AutoCompletionTextInputBinding; import org.jabref.gui.autocompleter.PersonNameStringConverter; import org.jabref.gui.autocompleter.SuggestionProvider; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.keyboard.KeyBindingRepository; @@ -239,7 +238,7 @@ private void initSearchModifierButtons() { initSearchModifierButton(openGlobalSearchButton); openGlobalSearchButton.setOnAction(evt -> { globalSearchActive.setValue(true); - globalSearchResultDialog = new GlobalSearchResultDialog(ExternalFileTypes.getInstance(), undoManager); + globalSearchResultDialog = new GlobalSearchResultDialog(undoManager); performSearch(); globalSearchResultDialog.showAndWait(); globalSearchActive.setValue(false); diff --git a/src/main/java/org/jabref/gui/search/GlobalSearchResultDialog.java b/src/main/java/org/jabref/gui/search/GlobalSearchResultDialog.java index 59843b2e4cb..b23dc8ab2df 100644 --- a/src/main/java/org/jabref/gui/search/GlobalSearchResultDialog.java +++ b/src/main/java/org/jabref/gui/search/GlobalSearchResultDialog.java @@ -11,7 +11,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.maintable.columns.SpecialFieldColumn; import org.jabref.gui.preview.PreviewViewer; @@ -28,7 +27,6 @@ public class GlobalSearchResultDialog extends BaseDialog { @FXML private SplitPane container; @FXML private ToggleButton keepOnTop; - private final ExternalFileTypes externalFileTypes; private final UndoManager undoManager; @Inject private PreferencesService preferencesService; @@ -38,9 +36,8 @@ public class GlobalSearchResultDialog extends BaseDialog { private GlobalSearchResultDialogViewModel viewModel; - public GlobalSearchResultDialog(ExternalFileTypes externalFileTypes, UndoManager undoManager) { + public GlobalSearchResultDialog(UndoManager undoManager) { this.undoManager = undoManager; - this.externalFileTypes = externalFileTypes; setTitle(Localization.lang("Search results from open libraries")); ViewLoader.view(this) @@ -57,7 +54,7 @@ private void initialize() { previewViewer.setLayout(preferencesService.getPreviewPreferences().getSelectedPreviewLayout()); SearchResultsTableDataModel model = new SearchResultsTableDataModel(viewModel.getSearchDatabaseContext(), preferencesService, stateManager); - SearchResultsTable resultsTable = new SearchResultsTable(model, viewModel.getSearchDatabaseContext(), preferencesService, undoManager, dialogService, stateManager, externalFileTypes); + SearchResultsTable resultsTable = new SearchResultsTable(model, viewModel.getSearchDatabaseContext(), preferencesService, undoManager, dialogService, stateManager); resultsTable.getColumns().removeIf(col -> col instanceof SpecialFieldColumn); resultsTable.getSelectionModel().selectFirst(); diff --git a/src/main/java/org/jabref/gui/search/SearchResultsTable.java b/src/main/java/org/jabref/gui/search/SearchResultsTable.java index 09083921f7a..a0f3ac20ea6 100644 --- a/src/main/java/org/jabref/gui/search/SearchResultsTable.java +++ b/src/main/java/org/jabref/gui/search/SearchResultsTable.java @@ -10,7 +10,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; -import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.maintable.BibEntryTableViewModel; import org.jabref.gui.maintable.MainTable; import org.jabref.gui.maintable.MainTableColumnFactory; @@ -28,8 +27,7 @@ public SearchResultsTable(SearchResultsTableDataModel model, PreferencesService preferencesService, UndoManager undoManager, DialogService dialogService, - StateManager stateManager, - ExternalFileTypes externalFileTypes) { + StateManager stateManager) { super(); MainTablePreferences mainTablePreferences = preferencesService.getMainTablePreferences(); @@ -38,7 +36,6 @@ public SearchResultsTable(SearchResultsTableDataModel model, database, preferencesService, preferencesService.getSearchDialogColumnPreferences(), - externalFileTypes, undoManager, dialogService, stateManager).createColumns(); diff --git a/src/main/java/org/jabref/preferences/FilePreferences.java b/src/main/java/org/jabref/preferences/FilePreferences.java index a2f2c9e4a4b..037324fc1dd 100644 --- a/src/main/java/org/jabref/preferences/FilePreferences.java +++ b/src/main/java/org/jabref/preferences/FilePreferences.java @@ -1,7 +1,10 @@ package org.jabref.preferences; import java.nio.file.Path; +import java.util.Comparator; import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; @@ -9,7 +12,10 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableSet; +import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.model.strings.StringUtil; public class FilePreferences { @@ -24,6 +30,7 @@ public class FilePreferences { private final BooleanProperty downloadLinkedFiles = new SimpleBooleanProperty(); private final BooleanProperty fulltextIndexLinkedFiles = new SimpleBooleanProperty(); private final ObjectProperty workingDirectory = new SimpleObjectProperty<>(); + private final ObservableSet externalFileTypes = FXCollections.observableSet(new TreeSet<>(Comparator.comparing(ExternalFileType::getName))); public FilePreferences(String user, String mainFileDirectory, @@ -32,7 +39,8 @@ public FilePreferences(String user, String fileDirectoryPattern, boolean downloadLinkedFiles, boolean fulltextIndexLinkedFiles, - Path workingDirectory) { + Path workingDirectory, + Set externalFileTypes) { this.user.setValue(user); this.mainFileDirectory.setValue(mainFileDirectory); this.storeFilesRelativeToBibFile.setValue(storeFilesRelativeToBibFile); @@ -41,6 +49,7 @@ public FilePreferences(String user, this.downloadLinkedFiles.setValue(downloadLinkedFiles); this.fulltextIndexLinkedFiles.setValue(fulltextIndexLinkedFiles); this.workingDirectory.setValue(workingDirectory); + this.externalFileTypes.addAll(externalFileTypes); } public String getUser() { // Read only @@ -134,4 +143,8 @@ public ObjectProperty workingDirectoryProperty() { public void setWorkingDirectory(Path workingDirectory) { this.workingDirectory.set(workingDirectory); } + + public ObservableSet getExternalFileTypes() { + return this.externalFileTypes; + } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index d204f2f8900..b954e883683 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -42,6 +42,8 @@ import org.jabref.gui.autocompleter.AutoCompletePreferences; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.entryeditor.EntryEditorPreferences; +import org.jabref.gui.externalfiletype.ExternalFileType; +import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.groups.GroupViewMode; import org.jabref.gui.groups.GroupsPreferences; import org.jabref.gui.keyboard.KeyBindingRepository; @@ -2208,7 +2210,8 @@ public FilePreferences getFilePreferences() { get(IMPORT_FILEDIRPATTERN), getBoolean(DOWNLOAD_LINKED_FILES), getBoolean(FULLTEXT_INDEX_LINKED_FILES), - Path.of(get(WORKING_DIRECTORY)) + Path.of(get(WORKING_DIRECTORY)), + ExternalFileTypes.fromString(get(EXTERNAL_FILE_TYPES)) ); EasyBind.listen(filePreferences.mainFileDirectoryProperty(), (obs, oldValue, newValue) -> put(MAIN_FILE_DIRECTORY, newValue)); @@ -2218,6 +2221,8 @@ public FilePreferences getFilePreferences() { EasyBind.listen(filePreferences.downloadLinkedFilesProperty(), (obs, oldValue, newValue) -> putBoolean(DOWNLOAD_LINKED_FILES, newValue)); EasyBind.listen(filePreferences.fulltextIndexLinkedFilesProperty(), (obs, oldValue, newValue) -> putBoolean(FULLTEXT_INDEX_LINKED_FILES, newValue)); EasyBind.listen(filePreferences.workingDirectoryProperty(), (obs, oldValue, newValue) -> put(WORKING_DIRECTORY, newValue.toString())); + filePreferences.getExternalFileTypes().addListener((SetChangeListener) c -> + put(EXTERNAL_FILE_TYPES, ExternalFileTypes.toStringList(filePreferences.getExternalFileTypes()))); return filePreferences; } @@ -2759,16 +2764,6 @@ public void storeLastPreferencesExportPath(Path exportFile) { put(PREFS_EXPORT_PATH, exportFile.toString()); } - @Override - public Optional getExternalFileTypes() { - return Optional.ofNullable(get(EXTERNAL_FILE_TYPES, null)); - } - - @Override - public void storeExternalFileTypes(String externalFileTypes) { - put(EXTERNAL_FILE_TYPES, externalFileTypes); - } - @Override public MrDlibPreferences getMrDlibPreferences() { if (Objects.nonNull(mrDlibPreferences)) { diff --git a/src/main/java/org/jabref/preferences/PreferencesService.java b/src/main/java/org/jabref/preferences/PreferencesService.java index 3e80aa2dde3..d3f7c692248 100644 --- a/src/main/java/org/jabref/preferences/PreferencesService.java +++ b/src/main/java/org/jabref/preferences/PreferencesService.java @@ -3,7 +3,6 @@ import java.nio.file.Path; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.prefs.BackingStoreException; @@ -278,10 +277,6 @@ public interface PreferencesService { void storeLastPreferencesExportPath(Path exportFile); - Optional getExternalFileTypes(); - - void storeExternalFileTypes(String externalFileTypes); - MrDlibPreferences getMrDlibPreferences(); ProtectedTermsPreferences getProtectedTermsPreferences(); diff --git a/src/test/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtilTest.java b/src/test/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtilTest.java index 22c73109876..b429b879454 100644 --- a/src/test/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtilTest.java +++ b/src/test/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtilTest.java @@ -6,6 +6,8 @@ import java.util.List; import java.util.TreeSet; +import javafx.collections.FXCollections; + import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.logic.util.io.AutoLinkPreferences; import org.jabref.model.database.BibDatabaseContext; @@ -25,14 +27,13 @@ public class AutoSetFileLinksUtilTest { - private final FilePreferences fileDirPrefs = mock(FilePreferences.class); + private final FilePreferences filePreferences = mock(FilePreferences.class); private final AutoLinkPreferences autoLinkPrefs = new AutoLinkPreferences( AutoLinkPreferences.CitationKeyDependency.START, "", false, ';'); private final BibDatabaseContext databaseContext = mock(BibDatabaseContext.class); - private final ExternalFileTypes externalFileTypes = mock(ExternalFileTypes.class); private final BibEntry entry = new BibEntry(StandardEntryType.Article); private Path path = null; @@ -41,23 +42,23 @@ public void setUp(@TempDir Path folder) throws Exception { path = folder.resolve("CiteKey.pdf"); Files.createFile(path); entry.setCitationKey("CiteKey"); - when(externalFileTypes.getExternalFileTypeSelection()).thenReturn(new TreeSet<>(ExternalFileTypes.getDefaultExternalFileTypes())); + when(filePreferences.getExternalFileTypes()) + .thenReturn(FXCollections.observableSet(new TreeSet<>(ExternalFileTypes.getDefaultExternalFileTypes()))); } @Test public void testFindAssociatedNotLinkedFilesSuccess() throws Exception { - // Due to mocking the externalFileType class, the file extension will not be found when(databaseContext.getFileDirectories(any())).thenReturn(Collections.singletonList(path.getParent())); - List expected = Collections.singletonList(new LinkedFile("", Path.of("CiteKey.pdf"), "")); - AutoSetFileLinksUtil util = new AutoSetFileLinksUtil(databaseContext, fileDirPrefs, autoLinkPrefs, externalFileTypes); + List expected = Collections.singletonList(new LinkedFile("", Path.of("CiteKey.pdf"), "PDF")); + AutoSetFileLinksUtil util = new AutoSetFileLinksUtil(databaseContext, filePreferences, autoLinkPrefs); List actual = util.findAssociatedNotLinkedFiles(entry); assertEquals(expected, actual); } @Test public void testFindAssociatedNotLinkedFilesForEmptySearchDir() throws Exception { - when(fileDirPrefs.shouldStoreFilesRelativeToBibFile()).thenReturn(false); - AutoSetFileLinksUtil util = new AutoSetFileLinksUtil(databaseContext, fileDirPrefs, autoLinkPrefs, externalFileTypes); + when(filePreferences.shouldStoreFilesRelativeToBibFile()).thenReturn(false); + AutoSetFileLinksUtil util = new AutoSetFileLinksUtil(databaseContext, filePreferences, autoLinkPrefs); List actual = util.findAssociatedNotLinkedFiles(entry); assertEquals(Collections.emptyList(), actual); } diff --git a/src/test/java/org/jabref/gui/externalfiletype/ExternalFileTypesTest.java b/src/test/java/org/jabref/gui/externalfiletype/ExternalFileTypesTest.java new file mode 100644 index 00000000000..dadcba319fc --- /dev/null +++ b/src/test/java/org/jabref/gui/externalfiletype/ExternalFileTypesTest.java @@ -0,0 +1,121 @@ +package org.jabref.gui.externalfiletype; + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Optional; +import java.util.Set; + +import javafx.collections.FXCollections; + +import org.jabref.gui.icon.IconTheme; +import org.jabref.model.entry.LinkedFile; +import org.jabref.preferences.FilePreferences; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class ExternalFileTypesTest { + private static final Set TEST_LIST = Set.of( + StandardExternalFileType.PDF, + StandardExternalFileType.URL, + StandardExternalFileType.JPG, + StandardExternalFileType.TXT); + + private static final String TEST_STRINGLIST = "PostScript:REMOVED;" + + "Word:REMOVED;" + + "Word 2007+:REMOVED;" + + "OpenDocument text:REMOVED;" + + "Excel:REMOVED;" + + "Excel 2007+:REMOVED;" + + "OpenDocument spreadsheet:REMOVED;" + + "PowerPoint:REMOVED;" + + "PowerPoint 2007+:REMOVED;" + + "OpenDocument presentation:REMOVED;" + + "Rich Text Format:REMOVED;" + + "PNG image:REMOVED;" + + "GIF image:REMOVED;" + + "Djvu:REMOVED;" + + "LaTeX:REMOVED;" + + "CHM:REMOVED;" + + "TIFF image:REMOVED;" + + "MHT:REMOVED;" + + "ePUB:REMOVED"; + + private final FilePreferences filePreferences = mock(FilePreferences.class); + + @BeforeEach + void setUp() { + when(filePreferences.getExternalFileTypes()).thenReturn(FXCollections.observableSet(TEST_LIST)); + } + + @Test + void getExternalFileTypeByName() { + assertEquals(Optional.of(StandardExternalFileType.PDF), ExternalFileTypes.getExternalFileTypeByName("PDF", filePreferences)); + } + + @Test + void getExternalFileTypeByExt() { + assertEquals(Optional.of(StandardExternalFileType.URL), ExternalFileTypes.getExternalFileTypeByExt("html", filePreferences)); + } + + @Test + void isExternalFileTypeByExt() { + assertTrue(ExternalFileTypes.isExternalFileTypeByExt("html", filePreferences)); + assertFalse(ExternalFileTypes.isExternalFileTypeByExt("tst", filePreferences)); + } + + @Test + void getExternalFileTypeForName() { + assertEquals(Optional.of(StandardExternalFileType.JPG), ExternalFileTypes.getExternalFileTypeForName("testfile.jpg", filePreferences)); + } + + @Test + void getExternalFileTypeByMimeType() { + assertEquals(Optional.of(StandardExternalFileType.TXT), ExternalFileTypes.getExternalFileTypeByMimeType("text/plain", filePreferences)); + } + + @Test + void getExternalFileTypeByFile() { + Path testfile = Path.of("testfile.txt"); + assertEquals(Optional.of(StandardExternalFileType.TXT), ExternalFileTypes.getExternalFileTypeByFile(testfile, filePreferences)); + } + + @Test + void getExternalFileTypeByLinkedFile() { + LinkedFile testfile = new LinkedFile("A testfile", "https://testserver.com/testfile.pdf", "PDF"); + assertEquals(Optional.of(StandardExternalFileType.PDF), ExternalFileTypes.getExternalFileTypeByLinkedFile(testfile, false, filePreferences)); + } + + @Test + void toStringList() { + String testString = ExternalFileTypes.toStringList(TEST_LIST); + + assertEquals(TEST_STRINGLIST, testString); + } + + @Test + void fromString() { + Set testList = ExternalFileTypes.fromString(TEST_STRINGLIST); + + assertEquals(TEST_LIST, testList); + } + + @Test + void externalFileTypetoStringArray() { + ExternalFileType type = new CustomExternalFileType( + "testEntry", + "tst", + "text/plain", + "emacs", + "close", + IconTheme.JabRefIcons.CLOSE); + + assertEquals("[testEntry, tst, text/plain, emacs, CLOSE]", Arrays.toString(type.toStringArray())); + } +} diff --git a/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java b/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java index e01d9f46594..e11100032c4 100644 --- a/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java +++ b/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java @@ -13,6 +13,7 @@ import java.util.Optional; import java.util.TreeSet; +import javafx.collections.FXCollections; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.ButtonType; @@ -45,7 +46,6 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.contains; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -62,7 +62,6 @@ class LinkedFileViewModelTest { private BibDatabaseContext databaseContext; private TaskExecutor taskExecutor; private DialogService dialogService; - private final ExternalFileTypes externalFileType = mock(ExternalFileTypes.class); private final FilePreferences filePreferences = mock(FilePreferences.class); private final PreferencesService preferences = mock(PreferencesService.class); private CookieManager cookieManager; @@ -75,11 +74,7 @@ void setUp(@TempDir Path tempFolder) throws Exception { taskExecutor = mock(TaskExecutor.class); dialogService = mock(DialogService.class); - when(externalFileType.getExternalFileTypeSelection()).thenReturn(new TreeSet<>(ExternalFileTypes.getDefaultExternalFileTypes())); - when(externalFileType.getExternalFileTypeByMimeType("application/pdf")).thenReturn(Optional.of(StandardExternalFileType.PDF)); - when(externalFileType.getExternalFileTypeByMimeType(contains("text/html"))).thenReturn(Optional.of(StandardExternalFileType.URL)); - when(externalFileType.getExternalFileTypeByExt("pdf")).thenReturn(Optional.of(StandardExternalFileType.PDF)); - when(externalFileType.getExternalFileTypeByExt("html")).thenReturn(Optional.of(StandardExternalFileType.URL)); + when(filePreferences.getExternalFileTypes()).thenReturn(FXCollections.observableSet(new TreeSet<>(ExternalFileTypes.getDefaultExternalFileTypes()))); when(preferences.getFilePreferences()).thenReturn(filePreferences); when(preferences.getXmpPreferences()).thenReturn(mock(XmpPreferences.class)); tempFile = tempFolder.resolve("temporaryFile"); @@ -106,7 +101,7 @@ void deleteWhenFilePathNotPresentReturnsTrue() { linkedFile = spy(new LinkedFile("", Path.of("nonexistent file"), "")); doReturn(Optional.empty()).when(linkedFile).findIn(any(BibDatabaseContext.class), any(FilePreferences.class)); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); boolean removed = viewModel.delete(); assertTrue(removed); @@ -124,7 +119,7 @@ void deleteWhenRemoveChosenReturnsTrueButDoesNotDeletesFile() { any(ButtonType.class), any(ButtonType.class))).thenAnswer(invocation -> Optional.of(invocation.getArgument(3))); // first vararg - remove button - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); boolean removed = viewModel.delete(); assertTrue(removed); @@ -142,7 +137,7 @@ void deleteWhenDeleteChosenReturnsTrueAndDeletesFile() { any(ButtonType.class), any(ButtonType.class))).thenAnswer(invocation -> Optional.of(invocation.getArgument(4))); // second vararg - delete button - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); boolean removed = viewModel.delete(); assertTrue(removed); @@ -160,7 +155,7 @@ void deleteMissingFileReturnsTrue() { any(ButtonType.class), any(ButtonType.class))).thenAnswer(invocation -> Optional.of(invocation.getArgument(4))); // second vararg - delete button - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); boolean removed = viewModel.delete(); assertTrue(removed); @@ -177,7 +172,7 @@ void deleteWhenDialogCancelledReturnsFalseAndDoesNotRemoveFile() { any(ButtonType.class), any(ButtonType.class))).thenAnswer(invocation -> Optional.of(invocation.getArgument(5))); // third vararg - cancel button - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); boolean removed = viewModel.delete(); assertFalse(removed); @@ -195,7 +190,7 @@ void downloadHtmlFileCausesWarningDisplay() throws MalformedURLException { String fileType = StandardExternalFileType.URL.getName(); linkedFile = new LinkedFile(url, fileType); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences); viewModel.download(); @@ -210,11 +205,11 @@ void downloadDoesNotOverwriteFileTypeExtension() throws MalformedURLException { when(filePreferences.getFileNamePattern()).thenReturn("[citationkey]"); when(filePreferences.getFileDirectoryPattern()).thenReturn(""); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences); BackgroundTask task = viewModel.prepareDownloadTask(tempFile.getParent(), new URLDownload("http://arxiv.org/pdf/1207.0408v1")); task.onSuccess(destination -> { - LinkedFile newLinkedFile = LinkedFilesEditorViewModel.fromFile(destination, Collections.singletonList(tempFile.getParent()), externalFileType); + LinkedFile newLinkedFile = LinkedFilesEditorViewModel.fromFile(destination, Collections.singletonList(tempFile.getParent()), filePreferences); assertEquals("asdf.pdf", newLinkedFile.getLink()); assertEquals("PDF", newLinkedFile.getFileType()); }); @@ -236,7 +231,7 @@ void downloadHtmlWhenLinkedFilePointsToHtml() throws MalformedURLException { databaseContext.setDatabasePath(tempFile); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences); viewModel.download(); @@ -260,7 +255,7 @@ void isNotSamePath() { when(filePreferences.getFileDirectoryPattern()).thenReturn(""); when(databaseContext.getFirstExistingFileDir(filePreferences)).thenReturn(Optional.of(Path.of("/home"))); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); assertFalse(viewModel.isGeneratedPathSameAsOriginal()); } @@ -272,7 +267,7 @@ void isSamePath() { when(filePreferences.getFileDirectoryPattern()).thenReturn(""); when(databaseContext.getFirstExistingFileDir(filePreferences)).thenReturn(Optional.of(tempFile.getParent())); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); assertTrue(viewModel.isGeneratedPathSameAsOriginal()); } @@ -285,7 +280,7 @@ void isNotSamePathWithPattern() { when(filePreferences.getFileDirectoryPattern()).thenReturn("[entrytype]"); when(databaseContext.getFirstExistingFileDir(filePreferences)).thenReturn(Optional.of(tempFile.getParent())); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); assertFalse(viewModel.isGeneratedPathSameAsOriginal()); } @@ -301,14 +296,14 @@ void isSamePathWithPattern() throws IOException { LinkedFileHandler fileHandler = new LinkedFileHandler(linkedFile, entry, databaseContext, filePreferences); fileHandler.moveToDefaultDirectory(); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences); assertTrue(viewModel.isGeneratedPathSameAsOriginal()); } // Tests if added parameters to mimeType gets parsed to correct format. @Test void mimeTypeStringWithParameterIsReturnedAsWithoutParameter() { - Optional test = externalFileType.getExternalFileTypeByMimeType("text/html; charset=UTF-8"); + Optional test = ExternalFileTypes.getExternalFileTypeByMimeType("text/html; charset=UTF-8", filePreferences); String actual = test.get().toString(); assertEquals("URL", actual); } @@ -323,7 +318,7 @@ void downloadPdfFileWhenLinkedFilePointsToPdfUrl() throws MalformedURLException databaseContext.setDatabasePath(tempFile); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences); viewModel.download(); // Loop through downloaded files to check for filetype='pdf' From c82fc171e344db1e2a970bccde1567f63299ce64 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 12 Aug 2022 17:01:15 +0200 Subject: [PATCH 03/52] Keep EOL setting at backups (#9048) * Fix org.jabref.logic.autosaveandbackup.BackupManager#performBackup to use line ending of library * Fix typos * fix checkstyle Co-authored-by: Siedlerchr --- .../gui/exporter/SaveDatabaseAction.java | 4 +++- .../autosaveandbackup/BackupManager.java | 20 +++++++++---------- .../org/jabref/logic/util/io/FileUtil.java | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 685e1c0d28d..293e03d45be 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -228,11 +228,13 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { } private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding, SavePreferences.DatabaseSaveType saveType) throws SaveException { + // if this code is adapted, please also adapt org.jabref.logic.autosaveandbackup.BackupManager.performBackup + GeneralPreferences generalPreferences = this.preferences.getGeneralPreferences(); SavePreferences savePreferences = this.preferences.getSavePreferences() .withSaveType(saveType); + BibDatabaseContext bibDatabaseContext = libraryTab.getBibDatabaseContext(); try (AtomicFileWriter fileWriter = new AtomicFileWriter(file, encoding, savePreferences.shouldMakeBackup())) { - BibDatabaseContext bibDatabaseContext = libraryTab.getBibDatabaseContext(); BibWriter bibWriter = new BibWriter(fileWriter, bibDatabaseContext.getDatabase().getNewLineSeparator()); BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter(bibWriter, generalPreferences, savePreferences, entryTypesManager); diff --git a/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java b/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java index 948aca58bf5..65656f71f9a 100644 --- a/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java +++ b/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java @@ -1,7 +1,6 @@ package org.jabref.logic.autosaveandbackup; import java.io.IOException; -import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -20,7 +19,6 @@ import org.jabref.logic.exporter.SavePreferences; import org.jabref.logic.util.CoarseChangeFilter; import org.jabref.logic.util.DelayTaskThrottler; -import org.jabref.logic.util.OS; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.event.BibDatabaseContextChangedEvent; @@ -57,7 +55,7 @@ private BackupManager(BibDatabaseContext bibDatabaseContext, BibEntryTypesManage this.bibDatabaseContext = bibDatabaseContext; this.entryTypesManager = entryTypesManager; this.preferences = preferences; - this.throttler = new DelayTaskThrottler(15000); + this.throttler = new DelayTaskThrottler(15_000); changeFilter = new CoarseChangeFilter(bibDatabaseContext); changeFilter.registerListener(this); @@ -134,13 +132,13 @@ private Optional determineBackupPath() { } private void performBackup(Path backupPath) { - try { - Charset charset = bibDatabaseContext.getMetaData().getEncoding().orElse(StandardCharsets.UTF_8); - GeneralPreferences generalPreferences = preferences.getGeneralPreferences(); - SavePreferences savePreferences = preferences.getSavePreferences() - .withMakeBackup(false); - Writer writer = new AtomicFileWriter(backupPath, charset); - BibWriter bibWriter = new BibWriter(writer, OS.NEWLINE); + // code similar to org.jabref.gui.exporter.SaveDatabaseAction.saveDatabase + GeneralPreferences generalPreferences = preferences.getGeneralPreferences(); + SavePreferences savePreferences = preferences.getSavePreferences() + .withMakeBackup(false); + Charset encoding = bibDatabaseContext.getMetaData().getEncoding().orElse(StandardCharsets.UTF_8); + try (AtomicFileWriter fileWriter = new AtomicFileWriter(backupPath, encoding)) { + BibWriter bibWriter = new BibWriter(fileWriter, bibDatabaseContext.getDatabase().getNewLineSeparator()); new BibtexDatabaseWriter(bibWriter, generalPreferences, savePreferences, entryTypesManager) .saveDatabase(bibDatabaseContext); } catch (IOException e) { @@ -157,7 +155,7 @@ private void logIfCritical(Path backupPath, IOException e) { // do not print errors in field values into the log during autosave if (!isErrorInField) { - LOGGER.error("Error while saving to file" + backupPath, e); + LOGGER.error("Error while saving to file {}", backupPath, e); } } diff --git a/src/main/java/org/jabref/logic/util/io/FileUtil.java b/src/main/java/org/jabref/logic/util/io/FileUtil.java index ae6be08ba15..f60ff2b110c 100644 --- a/src/main/java/org/jabref/logic/util/io/FileUtil.java +++ b/src/main/java/org/jabref/logic/util/io/FileUtil.java @@ -193,7 +193,7 @@ public static boolean copyFile(Path pathToSourceFile, Path pathToDestinationFile * * @param fromFile The source filename to rename * @param toFile The target fileName - * @return True if the rename was successful, false if an exception occurred + * @return True if rename was successful, false if an exception occurred */ public static boolean renameFile(Path fromFile, Path toFile) { return renameFile(fromFile, toFile, false); @@ -204,8 +204,8 @@ public static boolean renameFile(Path fromFile, Path toFile) { * * @param fromFile The source filename to rename * @param toFile The target fileName - * @param replaceExisting Wether to replace existing files or not - * @return True if the rename was successful, false if an exception occurred + * @param replaceExisting Whether to replace existing files or not + * @return True if rename was successful, false if an exception occurred * @deprecated Use {@link Files#move(Path, Path, CopyOption...)} instead and handle exception properly */ @Deprecated From 0b580790d7a323ccdb445b8a8a6e8dd4d5917e69 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Fri, 12 Aug 2022 17:02:25 +0200 Subject: [PATCH 04/52] Fixed table update in eft preferences (#9051) --- .../EditExternalFileTypeEntryDialog.fxml | 38 +++++------ .../EditExternalFileTypeEntryDialog.java | 11 +-- .../EditExternalFileTypeViewModel.java | 50 +++++++------- .../ExternalFileTypeItemViewModel.java | 68 +++++++++++++++++++ .../ExternalFileTypesTab.fxml | 2 +- .../ExternalFileTypesTab.java | 55 ++++++++++----- .../ExternalFileTypesTabViewModel.java | 62 ++++++++--------- 7 files changed, 185 insertions(+), 101 deletions(-) rename src/main/java/org/jabref/gui/{externalfiletype => preferences/externalfiletypes}/EditExternalFileTypeEntryDialog.fxml (51%) rename src/main/java/org/jabref/gui/{externalfiletype => preferences/externalfiletypes}/EditExternalFileTypeEntryDialog.java (90%) rename src/main/java/org/jabref/gui/{externalfiletype => preferences/externalfiletypes}/EditExternalFileTypeViewModel.java (65%) create mode 100644 src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypeItemViewModel.java diff --git a/src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypeEntryDialog.fxml b/src/main/java/org/jabref/gui/preferences/externalfiletypes/EditExternalFileTypeEntryDialog.fxml similarity index 51% rename from src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypeEntryDialog.fxml rename to src/main/java/org/jabref/gui/preferences/externalfiletypes/EditExternalFileTypeEntryDialog.fxml index 2e885d60011..d197a829648 100644 --- a/src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypeEntryDialog.fxml +++ b/src/main/java/org/jabref/gui/preferences/externalfiletypes/EditExternalFileTypeEntryDialog.fxml @@ -10,7 +10,7 @@ - + @@ -27,25 +27,23 @@ - - - - + + diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java index ce1c5f10e3e..ebd7e89619f 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionView.java @@ -13,7 +13,6 @@ import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.ButtonType; -import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; @@ -22,6 +21,7 @@ import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.control.cell.TextFieldTableCell; import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; import org.jabref.gui.DialogService; import org.jabref.gui.icon.IconTheme; @@ -29,23 +29,26 @@ import org.jabref.gui.util.BaseDialog; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.ValueTableCellFactory; -import org.jabref.gui.util.ViewModelListCellFactory; +import org.jabref.gui.util.ViewModelTableRowFactory; import org.jabref.logic.l10n.Localization; import org.jabref.model.study.Study; import org.jabref.preferences.PreferencesService; import com.airhacks.afterburner.views.ViewLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This class controls the user interface of the study definition management dialog. The UI elements and their layout * are defined in the FXML file. */ public class ManageStudyDefinitionView extends BaseDialog { + private static final Logger LOGGER = LoggerFactory.getLogger(ManageStudyDefinitionView.class); + @FXML private TextField studyTitle; @FXML private TextField addAuthor; @FXML private TextField addResearchQuestion; @FXML private TextField addQuery; - @FXML private ComboBox databaseSelector; @FXML private TextField studyDirectory; @FXML private ButtonType saveButtonType; @@ -66,7 +69,6 @@ public class ManageStudyDefinitionView extends BaseDialog @FXML private TableView databaseTable; @FXML private TableColumn databaseEnabledColumn; @FXML private TableColumn databaseColumn; - @FXML private TableColumn databaseActionColumn; @Inject private DialogService dialogService; @Inject private PreferencesService prefs; @@ -80,7 +82,7 @@ public class ManageStudyDefinitionView extends BaseDialog /** * This can be used to either create new study objects or edit existing ones. * - * @param study null if a new study is created. Otherwise the study object to edit. + * @param study null if a new study is created. Otherwise, the study object to edit. * @param studyDirectory the directory where the study to edit is located (null if a new study is created) */ public ManageStudyDefinitionView(Study study, Path studyDirectory, Path workingDirectory) { @@ -118,11 +120,14 @@ private void setupSaveButton() { @FXML private void initialize() { - viewModel = new ManageStudyDefinitionViewModel( - study, - workingDirectory, - prefs.getImportFormatPreferences(), - prefs.getImporterPreferences()); + if (Objects.isNull(study)) { + viewModel = new ManageStudyDefinitionViewModel( + prefs.getImportFormatPreferences(), + prefs.getImporterPreferences()); + } else { + LOGGER.error("Not yet implemented"); + return; + } // Listen whether any databases are removed from selection -> Add back to the database selector studyTitle.textProperty().bindBidirectional(viewModel.titleProperty()); @@ -161,25 +166,24 @@ private void initQueriesTab() { } private void initDatabasesTab() { - new ViewModelListCellFactory().withText(StudyDatabaseItem::getName) - .install(databaseSelector); - databaseSelector.setItems(viewModel.getNonSelectedDatabases()); + new ViewModelTableRowFactory() + .withOnMouseClickedEvent((entry, event) -> { + if (event.getButton() == MouseButton.PRIMARY) { + entry.setEnabled(!entry.isEnabled()); + } + }) + .install(databaseTable); - setupCommonPropertiesForTables(databaseSelector, this::addDatabase, databaseColumn, databaseActionColumn); + databaseColumn.setReorderable(false); + databaseColumn.setCellFactory(TextFieldTableCell.forTableColumn()); databaseEnabledColumn.setResizable(false); databaseEnabledColumn.setReorderable(false); - databaseEnabledColumn.setCellValueFactory(param -> param.getValue().enabledProperty()); databaseEnabledColumn.setCellFactory(CheckBoxTableCell.forTableColumn(databaseEnabledColumn)); + databaseEnabledColumn.setCellValueFactory(param -> param.getValue().enabledProperty()); + databaseColumn.setEditable(false); databaseColumn.setCellValueFactory(param -> param.getValue().nameProperty()); - databaseActionColumn.setCellValueFactory(param -> param.getValue().nameProperty()); - new ValueTableCellFactory() - .withGraphic(item -> IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode()) - .withTooltip(name -> Localization.lang("Remove")) - .withOnMouseClickedEvent(item -> evt -> - viewModel.removeDatabase(item)) - .install(databaseActionColumn); databaseTable.setItems(viewModel.getDatabases()); } @@ -231,14 +235,6 @@ private void addQuery() { addQuery.setText(""); } - /** - * Add selected entry from combobox, push onto database pop from nonselecteddatabase (combobox) - */ - @FXML - private void addDatabase() { - viewModel.addDatabase(databaseSelector.getSelectionModel().getSelectedItem()); - } - @FXML public void selectStudyDirectory() { DirectoryDialogConfiguration directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder() diff --git a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java index 01350ab64bb..3f87b2232c3 100644 --- a/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java +++ b/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java @@ -2,9 +2,10 @@ import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.util.Comparator; +import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import javafx.beans.property.Property; @@ -17,6 +18,11 @@ import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.importer.SearchBasedFetcher; import org.jabref.logic.importer.WebFetchers; +import org.jabref.logic.importer.fetcher.ACMPortalFetcher; +import org.jabref.logic.importer.fetcher.CompositeSearchBasedFetcher; +import org.jabref.logic.importer.fetcher.DBLPFetcher; +import org.jabref.logic.importer.fetcher.IEEE; +import org.jabref.logic.importer.fetcher.SpringerFetcher; import org.jabref.model.study.Study; import org.jabref.model.study.StudyDatabase; import org.jabref.model.study.StudyQuery; @@ -31,45 +37,69 @@ public class ManageStudyDefinitionViewModel { private static final Logger LOGGER = LoggerFactory.getLogger(ManageStudyDefinitionViewModel.class); + private static final Set DEFAULT_SELECTION = Set.of( + ACMPortalFetcher.FETCHER_NAME, + IEEE.FETCHER_NAME, + SpringerFetcher.FETCHER_NAME, + DBLPFetcher.FETCHER_NAME); + + private final StringProperty title = new SimpleStringProperty(); private final ObservableList authors = FXCollections.observableArrayList(); private final ObservableList researchQuestions = FXCollections.observableArrayList(); private final ObservableList queries = FXCollections.observableArrayList(); private final ObservableList databases = FXCollections.observableArrayList(); + // Hold the complement of databases for the selector - private final ObservableList nonSelectedDatabases = FXCollections.observableArrayList(); private final SimpleStringProperty directory = new SimpleStringProperty(); - private Study study; + /** + * Constructor for a new study + */ + public ManageStudyDefinitionViewModel(ImportFormatPreferences importFormatPreferences, + ImporterPreferences importerPreferences) { + databases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) + .stream() + .map(SearchBasedFetcher::getName) + // The user wants to select specific fetchers + // The fetcher summarizing ALL fetchers can be emulated by selecting ALL fetchers (which happens rarely when doing an SLR) + .filter(name -> !name.equals(CompositeSearchBasedFetcher.FETCHER_NAME)) + .map(name -> { + boolean enabled = DEFAULT_SELECTION.contains(name); + return new StudyDatabaseItem(name, enabled); + }) + .toList()); + } + + /** + * Constructor for an existing study + * + * @param study The study to initialize the UI from + * @param studyDirectory The path where the study resides + */ public ManageStudyDefinitionViewModel(Study study, Path studyDirectory, ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences) { - if (Objects.isNull(study)) { - computeNonSelectedDatabases(importFormatPreferences, importerPreferences); - return; - } - this.study = study; + // copy the content of the study object into the UI fields + authors.addAll(Objects.requireNonNull(study).getAuthors()); title.setValue(study.getTitle()); - authors.addAll(study.getAuthors()); researchQuestions.addAll(study.getResearchQuestions()); queries.addAll(study.getQueries().stream().map(StudyQuery::getQuery).toList()); - databases.addAll(study.getDatabases() - .stream() - .map(studyDatabase -> new StudyDatabaseItem(studyDatabase.getName(), studyDatabase.isEnabled())) - .toList()); - computeNonSelectedDatabases(importFormatPreferences, importerPreferences); - if (!Objects.isNull(studyDirectory)) { - this.directory.set(studyDirectory.toString()); - } - } - - private void computeNonSelectedDatabases(ImportFormatPreferences importFormatPreferences, ImporterPreferences importerPreferences) { - nonSelectedDatabases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) - .stream() - .map(SearchBasedFetcher::getName) - .map(s -> new StudyDatabaseItem(s, true)) - .filter(studyDatabase -> !databases.contains(studyDatabase)).toList()); + List studyDatabases = study.getDatabases(); + databases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences) + .stream() + .map(SearchBasedFetcher::getName) + // The user wants to select specific fetchers + // The fetcher summarizing ALL fetchers can be emulated by selecting ALL fetchers (which happens rarely when doing an SLR) + .filter(name -> !name.equals(CompositeSearchBasedFetcher.FETCHER_NAME)) + .map(name -> { + boolean enabled = studyDatabases.contains(new StudyDatabase(name, true)); + return new StudyDatabaseItem(name, enabled); + }) + .toList()); + + this.directory.set(Objects.requireNonNull(studyDirectory).toString()); } public StringProperty getTitle() { @@ -96,10 +126,6 @@ public ObservableList getDatabases() { return databases; } - public ObservableList getNonSelectedDatabases() { - return nonSelectedDatabases; - } - public void addAuthor(String author) { if (author.isBlank()) { return; @@ -121,29 +147,18 @@ public void addQuery(String query) { queries.add(query); } - public void addDatabase(StudyDatabaseItem database) { - if (Objects.isNull(database)) { - return; - } - nonSelectedDatabases.remove(database); - if (!databases.contains(database)) { - databases.add(database); - } - } - public SlrStudyAndDirectory saveStudy() { - if (Objects.isNull(study)) { - study = new Study(); - } - study.setTitle(title.getValueSafe()); - study.setAuthors(authors); - study.setResearchQuestions(researchQuestions); - study.setQueries(queries.stream().map(StudyQuery::new).collect(Collectors.toList())); - study.setDatabases(databases.stream().map(studyDatabaseItem -> new StudyDatabase(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).collect(Collectors.toList())); + Study study = new Study( + authors, + title.getValueSafe(), + researchQuestions, + queries.stream().map(StudyQuery::new).collect(Collectors.toList()), + databases.stream().map(studyDatabaseItem -> new StudyDatabase(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).filter(StudyDatabase::isEnabled).collect(Collectors.toList())); Path studyDirectory = null; try { studyDirectory = Path.of(directory.getValueSafe()); - } catch (InvalidPathException e) { + } catch ( + InvalidPathException e) { LOGGER.error("Invalid path was provided: {}", directory); } return new SlrStudyAndDirectory(study, studyDirectory); @@ -153,20 +168,6 @@ public Property titleProperty() { return title; } - public void removeDatabase(String database) { - // If a database is added from the combo box it should be enabled by default - Optional correspondingDatabase = databases.stream().filter(studyDatabaseItem -> studyDatabaseItem.getName().equals(database)).findFirst(); - if (correspondingDatabase.isEmpty()) { - return; - } - StudyDatabaseItem databaseToRemove = correspondingDatabase.get(); - databases.remove(databaseToRemove); - databaseToRemove.setEnabled(true); - nonSelectedDatabases.add(databaseToRemove); - // Resort list - nonSelectedDatabases.sort(Comparator.comparing(StudyDatabaseItem::getName)); - } - public void setStudyDirectory(Optional studyRepositoryRoot) { getDirectory().setValue(studyRepositoryRoot.map(Path::toString).orElseGet(() -> getDirectory().getValueSafe())); } diff --git a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java index 50ceda09143..c6c77eaaf31 100644 --- a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java +++ b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java @@ -1,16 +1,23 @@ package org.jabref.gui.slr; +import java.util.Objects; + import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import org.jabref.model.study.StudyDatabase; + +/** + * View representation of {@link StudyDatabase} + */ public class StudyDatabaseItem { private final StringProperty name; private final BooleanProperty enabled; public StudyDatabaseItem(String name, boolean enabled) { - this.name = new SimpleStringProperty(name); + this.name = new SimpleStringProperty(Objects.requireNonNull(name)); this.enabled = new SimpleBooleanProperty(enabled); } @@ -38,6 +45,14 @@ public BooleanProperty enabledProperty() { return enabled; } + @Override + public String toString() { + return "StudyDatabaseItem{" + + "name=" + name.get() + + ", enabled=" + enabled.get() + + '}'; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -46,19 +61,12 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - StudyDatabaseItem that = (StudyDatabaseItem) o; - - if (isEnabled() != that.isEnabled()) { - return false; - } - return getName() != null ? getName().equals(that.getName()) : that.getName() == null; + return Object.equals(getName(),that.getName()) && Object.equals(isEnabled(), that.isEnabled()); } @Override public int hashCode() { - int result = getName() != null ? getName().hashCode() : 0; - result = 31 * result + (isEnabled() ? 1 : 0); - return result; + return Objects.hash(getName(), isEnabled()); } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ACMPortalFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/ACMPortalFetcher.java index 10ba0e1b1b4..5fd153a07f2 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ACMPortalFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ACMPortalFetcher.java @@ -19,6 +19,8 @@ public class ACMPortalFetcher implements SearchBasedParserFetcher { + public static final String FETCHER_NAME = "ACM Portal"; + private static final String SEARCH_URL = "https://dl.acm.org/action/doSearch"; public ACMPortalFetcher() { @@ -28,7 +30,7 @@ public ACMPortalFetcher() { @Override public String getName() { - return "ACM Portal"; + return FETCHER_NAME; } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/CompositeSearchBasedFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/CompositeSearchBasedFetcher.java index 97506c284a6..bee6f3c7fc9 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/CompositeSearchBasedFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/CompositeSearchBasedFetcher.java @@ -17,6 +17,8 @@ public class CompositeSearchBasedFetcher implements SearchBasedFetcher { + public static final String FETCHER_NAME = "SearchAll"; + private static final Logger LOGGER = LoggerFactory.getLogger(CompositeSearchBasedFetcher.class); private final Set fetchers; @@ -36,7 +38,7 @@ public CompositeSearchBasedFetcher(Set searchBasedFetchers, @Override public String getName() { - return "SearchAll"; + return FETCHER_NAME; } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/DBLPFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/DBLPFetcher.java index d961ce0b3bc..19d1d67ec1a 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/DBLPFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/DBLPFetcher.java @@ -33,6 +33,7 @@ * @see Basic API documentation */ public class DBLPFetcher implements SearchBasedParserFetcher { + public static final String FETCHER_NAME = "DBLP"; private static final String BASIC_SEARCH_URL = "https://dblp.org/search/publ/api"; @@ -76,7 +77,7 @@ public void doPostCleanup(BibEntry entry) { @Override public String getName() { - return "DBLP"; + return FETCHER_NAME; } @Override diff --git a/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java b/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java index 3ca57ff3cbf..fe9860c3f44 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/IEEE.java @@ -48,9 +48,9 @@ */ public class IEEE implements FulltextFetcher, PagedSearchBasedParserFetcher, CustomizableKeyFetcher { - private static final Logger LOGGER = LoggerFactory.getLogger(IEEE.class); + public static final String FETCHER_NAME = "IEEEXplore"; - private static final String FETCHER_NAME = "IEEEXplore"; + private static final Logger LOGGER = LoggerFactory.getLogger(IEEE.class); private static final String STAMP_BASE_STRING_DOCUMENT = "/stamp/stamp.jsp?tp=&arnumber="; private static final Pattern STAMP_PATTERN = Pattern.compile("(/stamp/stamp.jsp\\?t?p?=?&?arnumber=[0-9]+)"); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java index d0aa60e4494..e1764120e14 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java @@ -40,13 +40,14 @@ */ public class SpringerFetcher implements PagedSearchBasedParserFetcher, CustomizableKeyFetcher { + public static final String FETCHER_NAME = "Springer"; + private static final Logger LOGGER = LoggerFactory.getLogger(SpringerFetcher.class); private static final String API_URL = "https://api.springernature.com/meta/v1/json"; private static final String API_KEY = new BuildInfo().springerNatureAPIKey; // Springer query using the parameter 'q=doi:10.1007/s11276-008-0131-4s=1' will respond faster private static final String TEST_URL_WITHOUT_API_KEY = "https://api.springernature.com/meta/v1/json?q=doi:10.1007/s11276-008-0131-4s=1&p=1&api_key="; - private static final String FETCHER_NAME = "Springer"; private final ImporterPreferences importerPreferences; diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SpringerLink.java b/src/main/java/org/jabref/logic/importer/fetcher/SpringerLink.java index 78a7a420718..769e7f6c200 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/SpringerLink.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/SpringerLink.java @@ -27,12 +27,13 @@ * Uses Springer API, see https://dev.springer.com */ public class SpringerLink implements FulltextFetcher { + public static final String FETCHER_NAME = "Springer"; + private static final Logger LOGGER = LoggerFactory.getLogger(SpringerLink.class); private static final String API_URL = "https://api.springer.com/meta/v1/json"; private static final String API_KEY = new BuildInfo().springerNatureAPIKey; private static final String CONTENT_HOST = "link.springer.com"; - private static final String FETCHER_NAME = "Springer"; private final ImporterPreferences importerPreferences; diff --git a/src/main/java/org/jabref/model/study/Study.java b/src/main/java/org/jabref/model/study/Study.java index 1c85a1d77c2..3748f0962bc 100644 --- a/src/main/java/org/jabref/model/study/Study.java +++ b/src/main/java/org/jabref/model/study/Study.java @@ -35,7 +35,7 @@ public Study(List authors, String title, List researchQuestions, /** * Used for Jackson deserialization */ - public Study() { + private Study() { } public List getAuthors() { diff --git a/src/main/java/org/jabref/model/study/StudyDatabase.java b/src/main/java/org/jabref/model/study/StudyDatabase.java index ac71a7160c2..375b59fb57c 100644 --- a/src/main/java/org/jabref/model/study/StudyDatabase.java +++ b/src/main/java/org/jabref/model/study/StudyDatabase.java @@ -1,5 +1,8 @@ package org.jabref.model.study; +/** + * data model for the view {@link org.jabref.gui.slr.StudyDatabaseItem} + */ public class StudyDatabase { private String name; private boolean enabled; diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 6dff22b68d0..d020d8e5691 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2406,7 +2406,7 @@ Database=Database Databases=Databases Manage\ study\ definition=Manage study definition Add\ Author\:=Add Author\: -Add\ Database\:=Add Database\: +Select\ Databases\:=Select the databases that should be searched\: Add\ Query\:=Add Query\: Add\ Research\ Question\:=Add Research Question\: Perform\ search\ for\ existing\ systematic\ literature\ review=Perform search for existing systematic literature review diff --git a/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java b/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java new file mode 100644 index 00000000000..f6f9d927909 --- /dev/null +++ b/src/test/java/org/jabref/gui/slr/ManageStudyDefinitionViewModelTest.java @@ -0,0 +1,98 @@ +package org.jabref.gui.slr; + +import java.nio.file.Path; +import java.util.List; + +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; +import org.jabref.logic.importer.ImportFormatPreferences; +import org.jabref.logic.importer.ImporterPreferences; +import org.jabref.model.study.Study; +import org.jabref.model.study.StudyDatabase; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.Answers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class ManageStudyDefinitionViewModelTest { + private ImportFormatPreferences importFormatPreferences; + private ImporterPreferences importerPreferences; + + @BeforeEach + void setUp() { + // code taken from org.jabref.logic.importer.WebFetchersTest.setUp + importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); + importerPreferences = mock(ImporterPreferences.class); + FieldContentFormatterPreferences fieldContentFormatterPreferences = mock(FieldContentFormatterPreferences.class); + when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn(fieldContentFormatterPreferences); + } + + @Test + public void emptyStudyConstructorFillsDatabasesCorrectly() { + ManageStudyDefinitionViewModel manageStudyDefinitionViewModel = new ManageStudyDefinitionViewModel(importFormatPreferences, importerPreferences); + assertEquals(List.of( + new StudyDatabaseItem("ACM Portal", true), + new StudyDatabaseItem("ArXiv", false), + new StudyDatabaseItem("Biodiversity Heritage", false), + new StudyDatabaseItem("CiteSeerX", false), + new StudyDatabaseItem("Collection of Computer Science Bibliographies", false), + new StudyDatabaseItem("Crossref", false), + new StudyDatabaseItem("DBLP", true), + new StudyDatabaseItem("DOAB", false), + new StudyDatabaseItem("DOAJ", false), + new StudyDatabaseItem("GVK", false), + new StudyDatabaseItem("IEEEXplore", true), + new StudyDatabaseItem("INSPIRE", false), + new StudyDatabaseItem("MathSciNet", false), + new StudyDatabaseItem("Medline/PubMed", false), + new StudyDatabaseItem("ResearchGate", false), + new StudyDatabaseItem("SAO/NASA ADS", false), + new StudyDatabaseItem("SemanticScholar", false), + new StudyDatabaseItem("Springer", true), + new StudyDatabaseItem("zbMATH", false) + ), manageStudyDefinitionViewModel.getDatabases()); + } + + @Test + public void studyConstructorFillsDatabasesCorrectly(@TempDir Path tempDir) { + List databases = List.of( + new StudyDatabase("ACM Portal", true)); + Study study = new Study( + List.of("Name"), + "title", + List.of("Q1"), + List.of(), + databases + ); + ManageStudyDefinitionViewModel manageStudyDefinitionViewModel = new ManageStudyDefinitionViewModel( + study, + tempDir, + importFormatPreferences, + importerPreferences); + assertEquals(List.of( + new StudyDatabaseItem("ACM Portal", true), + new StudyDatabaseItem("ArXiv", false), + new StudyDatabaseItem("Biodiversity Heritage", false), + new StudyDatabaseItem("CiteSeerX", false), + new StudyDatabaseItem("Collection of Computer Science Bibliographies", false), + new StudyDatabaseItem("Crossref", false), + new StudyDatabaseItem("DBLP", false), + new StudyDatabaseItem("DOAB", false), + new StudyDatabaseItem("DOAJ", false), + new StudyDatabaseItem("GVK", false), + new StudyDatabaseItem("IEEEXplore", false), + new StudyDatabaseItem("INSPIRE", false), + new StudyDatabaseItem("MathSciNet", false), + new StudyDatabaseItem("Medline/PubMed", false), + new StudyDatabaseItem("ResearchGate", false), + new StudyDatabaseItem("SAO/NASA ADS", false), + new StudyDatabaseItem("SemanticScholar", false), + new StudyDatabaseItem("Springer", false), + new StudyDatabaseItem("zbMATH", false) + ), manageStudyDefinitionViewModel.getDatabases()); + } +} From ad9aa62e64fef703a80ef6dcc806b12d55f6f586 Mon Sep 17 00:00:00 2001 From: Hugo Rocha de Moura <54285732+hugorochaffs@users.noreply.github.com> Date: Sat, 3 Sep 2022 08:07:47 -0300 Subject: [PATCH 46/52] Fix integrity check for tilde accents in author names (#9097) * Solving tilde error in author names * Fixed checkstyle and removed superfluous new test class * remove latex html conversion and rtf chart * add test to authorlist parser * parameterized tests * fix test * fix test * Convert to parameterized test * fix test and checkstyle * fix checkstyle and tests * Fixed tabstop * add changelog Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Co-authored-by: Siedlerchr --- CHANGELOG.md | 1 + .../logic/importer/AuthorListParser.java | 2 +- .../strings/HTMLUnicodeConversionMaps.java | 2 +- .../jabref/logic/util/strings/RtfCharMap.java | 2 +- .../HtmlToUnicodeFormatterTest.java | 66 +++++++------------ .../logic/importer/AuthorListParserTest.java | 3 +- .../integrity/PersonNamesCheckerTest.java | 65 ++++++++---------- 7 files changed, 58 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 880b7b43b26..9a0cfc8b3ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve ### Fixed +- We fixed an issue where author names with tilde accents (for example ñ) were marked as "Names are not in the standard BibTex format" [#8071](https://github.com/JabRef/jabref/issues/8071) - We fixed an issue where the possibility to generate a subdatabase from an aux file was writing empty files when called from the commandline [#9115](https://github.com/JabRef/jabref/issues/9115), [forum#3516](https://discourse.jabref.org/t/export-subdatabase-from-aux-file-on-macos-command-line/3516) - We fixed the display of issue, number, eid and pages fields in the entry preview. [#8607](https://github.com/JabRef/jabref/pull/8607), [#8372](https://github.com/JabRef/jabref/issues/8372), [Koppor#514](https://github.com/koppor/jabref/issues/514), [forum#2390](https://discourse.jabref.org/t/unable-to-edit-my-bibtex-file-that-i-used-before-vers-5-1/2390), [forum#3462](https://discourse.jabref.org/t/jabref-5-6-need-help-with-export-from-jabref-to-microsoft-word-entry-preview-of-apa-7-not-rendering-correctly/3462) - We fixed the page ranges checker to detect article numbers in the pages field (used at [Check Integrity](https://docs.jabref.org/finding-sorting-and-cleaning-entries/checkintegrity)). [#8607](https://github.com/JabRef/jabref/pull/8607) diff --git a/src/main/java/org/jabref/logic/importer/AuthorListParser.java b/src/main/java/org/jabref/logic/importer/AuthorListParser.java index bc4835c92f2..41acfd2a503 100644 --- a/src/main/java/org/jabref/logic/importer/AuthorListParser.java +++ b/src/main/java/org/jabref/logic/importer/AuthorListParser.java @@ -447,7 +447,7 @@ private Token getToken() { if (c == '\\') { currentBackslash = tokenEnd; } - if ((bracesLevel == 0) && ((",;~-".indexOf(c) != -1) || Character.isWhitespace(c))) { + if ((bracesLevel == 0) && ((",;-".indexOf(c) != -1) || Character.isWhitespace(c))) { break; } tokenEnd++; diff --git a/src/main/java/org/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java b/src/main/java/org/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java index 587f7197218..86973053a09 100644 --- a/src/main/java/org/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java +++ b/src/main/java/org/jabref/logic/util/strings/HTMLUnicodeConversionMaps.java @@ -762,6 +762,7 @@ public class HTMLUnicodeConversionMaps { {"119978", "Oscr", "$\\mathcal{O}$"}, // script capital O -- possibly use \mathscr {"119984", "Uscr", "$\\mathcal{U}$"}, // script capital U -- possibly use \mathscr {"120598", "", "$\\epsilon$"}, // mathematical italic epsilon U+1D716 -- requires amsmath + {"120599", "", "{{\\˜{n}}}"}, // n with tide }; // List of combining accents @@ -888,7 +889,6 @@ public class HTMLUnicodeConversionMaps { // Manual corrections LATEX_HTML_CONVERSION_MAP.put("AA", "Å"); // Overwritten by Å which is less supported LATEX_UNICODE_CONVERSION_MAP.put("AA", "Å"); // Overwritten by Ångstrom symbol - LATEX_UNICODE_CONVERSION_MAP.put("'n", "ń"); // Manual additions // Support relax to the extent that it is simply removed diff --git a/src/main/java/org/jabref/logic/util/strings/RtfCharMap.java b/src/main/java/org/jabref/logic/util/strings/RtfCharMap.java index 46f49f37bfc..393f9685ffb 100644 --- a/src/main/java/org/jabref/logic/util/strings/RtfCharMap.java +++ b/src/main/java/org/jabref/logic/util/strings/RtfCharMap.java @@ -4,7 +4,7 @@ public class RtfCharMap { - private HashMap rtfMap = new HashMap<>(); + private final HashMap rtfMap = new HashMap<>(); public RtfCharMap() { put("`a", "\\'e0"); diff --git a/src/test/java/org/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java b/src/test/java/org/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java index 81997715f25..64f14737bb9 100644 --- a/src/test/java/org/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java +++ b/src/test/java/org/jabref/logic/formatter/bibtexfields/HtmlToUnicodeFormatterTest.java @@ -1,7 +1,11 @@ package org.jabref.logic.formatter.bibtexfields; +import java.util.stream.Stream; + import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -9,52 +13,28 @@ public class HtmlToUnicodeFormatterTest { private HtmlToUnicodeFormatter formatter; + private static Stream data() { + return Stream.of( + Arguments.of("abc", "abc"), + Arguments.of("åäö", "åäö"), + Arguments.of("í", "í"), + Arguments.of("Ε", "Ε"), + Arguments.of("ä", "ä"), + Arguments.of("ä", "ä"), + Arguments.of("ä", "ä"), + Arguments.of("ñ", "ñ"), + Arguments.of("aaa", "

aaa

"), + Arguments.of("bread & butter", "bread & butter")); + } + @BeforeEach public void setUp() { formatter = new HtmlToUnicodeFormatter(); } - @Test - public void formatWithoutHtmlCharactersReturnsSameString() { - assertEquals("abc", formatter.format("abc")); - } - - @Test - public void formatMultipleHtmlCharacters() { - assertEquals("åäö", formatter.format("åäö")); - } - - @Test - public void formatCombinedAccent() { - assertEquals("í", formatter.format("í")); - } - - @Test - public void testBasic() { - assertEquals("aaa", formatter.format("aaa")); - } - - @Test - public void testUmlauts() { - assertEquals("ä", formatter.format("ä")); - assertEquals("ä", formatter.format("ä")); - assertEquals("ä", formatter.format("ä")); - } - - @Test - public void testGreekLetter() { - assertEquals("Ε", formatter.format("Ε")); - } - - @Test - public void testHTMLRemoveTags() { - assertEquals("aaa", formatter.format("

aaa

")); - } - - @Test - public void formatExample() { - assertEquals("bread & butter", formatter.format(formatter.getExampleInput())); + @ParameterizedTest + @MethodSource("data") + void testFormatterWorksCorrectly(String expected, String input) { + assertEquals(expected, formatter.format(input)); } } - - diff --git a/src/test/java/org/jabref/logic/importer/AuthorListParserTest.java b/src/test/java/org/jabref/logic/importer/AuthorListParserTest.java index 7c765d283f9..1ec4e02879c 100644 --- a/src/test/java/org/jabref/logic/importer/AuthorListParserTest.java +++ b/src/test/java/org/jabref/logic/importer/AuthorListParserTest.java @@ -25,7 +25,8 @@ private static Stream data() { Arguments.of("de la Vallée Poussin, Jean Charles Gabriel", new Author("Jean Charles Gabriel", "J. C. G.", "de la", "Vallée Poussin", null)), Arguments.of("de la Vallée Poussin, J. C. G.", new Author("J. C. G.", "J. C. G.", "de la", "Vallée Poussin", null)), Arguments.of("{K}ent-{B}oswell, E. S.", new Author("E. S.", "E. S.", null, "{K}ent-{B}oswell", null)), - Arguments.of("Uhlenhaut, N Henriette", new Author("N Henriette", "N. H.", null, "Uhlenhaut", null)) + Arguments.of("Uhlenhaut, N Henriette", new Author("N Henriette", "N. H.", null, "Uhlenhaut", null)), + Arguments.of("Nu{\\~{n}}ez, Jose", new Author("Jose", "J.", null, "Nu{\\~{n}}ez", null)) ); } diff --git a/src/test/java/org/jabref/logic/integrity/PersonNamesCheckerTest.java b/src/test/java/org/jabref/logic/integrity/PersonNamesCheckerTest.java index e6ed2c2b743..b64900e6122 100644 --- a/src/test/java/org/jabref/logic/integrity/PersonNamesCheckerTest.java +++ b/src/test/java/org/jabref/logic/integrity/PersonNamesCheckerTest.java @@ -29,48 +29,35 @@ public void setUp() throws Exception { checkerb = new PersonNamesChecker(database); } - @Test - public void validNameFirstnameAuthor() throws Exception { - assertEquals(Optional.empty(), checker.checkValue("Kolb, Stefan")); + @ParameterizedTest + @MethodSource("provideValidNames") + public void validNames(String name) { + assertEquals(Optional.empty(), checker.checkValue(name)); } - @Test - public void validNameFirstnameAuthors() throws Exception { - assertEquals(Optional.empty(), checker.checkValue("Kolb, Stefan and Harrer, Simon")); - } + private static Stream provideValidNames() { + return Stream.of( + "Kolb, Stefan", // single [Name, Firstname] + "Kolb, Stefan and Harrer, Simon", // multiple [Name, Firstname] + "Stefan Kolb", // single [Firstname Name] + "Stefan Kolb and Simon Harrer", // multiple [Firstname Name] - @Test - public void validFirstnameNameAuthor() throws Exception { - assertEquals(Optional.empty(), checker.checkValue("Stefan Kolb")); - } + "M. J. Gotay", // second name in front - @Test - public void validFirstnameNameAuthors() throws Exception { - assertEquals(Optional.empty(), checker.checkValue("Stefan Kolb and Simon Harrer")); + "{JabRef}", // corporate name in brackets + "{JabRef} and Stefan Kolb", // mixed corporate name with name + "{JabRef} and Kolb, Stefan", + + "hugo Para{\\~n}os" // tilde in name + ); } @Test - public void complainAboutPersonStringWithTwoManyCommas() throws Exception { + public void complainAboutPersonStringWithTwoManyCommas() { assertEquals(Optional.of("Names are not in the standard BibTeX format."), checker.checkValue("Test1, Test2, Test3, Test4, Test5, Test6")); } - @Test - public void doNotComplainAboutSecondNameInFront() throws Exception { - assertEquals(Optional.empty(), checker.checkValue("M. J. Gotay")); - } - - @Test - public void validCorporateNameInBrackets() throws Exception { - assertEquals(Optional.empty(), checker.checkValue("{JabRef}")); - } - - @Test - public void validCorporateNameAndPerson() throws Exception { - assertEquals(Optional.empty(), checker.checkValue("{JabRef} and Stefan Kolb")); - assertEquals(Optional.empty(), checker.checkValue("{JabRef} and Kolb, Stefan")); - } - @ParameterizedTest @MethodSource("provideCorrectFormats") public void authorNameInCorrectFormatsShouldNotComplain(String input) { @@ -84,13 +71,19 @@ public void authorNameInIncorrectFormatsShouldComplain(String input) { } private static Stream provideCorrectFormats() { - return Stream.of("", "Knuth", "Donald E. Knuth and Kurt Cobain and A. Einstein"); + return Stream.of( + "", + "Knuth", + "Donald E. Knuth and Kurt Cobain and A. Einstein"); } private static Stream provideIncorrectFormats() { - return Stream.of(" Knuth, Donald E. ", - "Knuth, Donald E. and Kurt Cobain and A. Einstein", - ", and Kurt Cobain and A. Einstein", "Donald E. Knuth and Kurt Cobain and ,", - "and Kurt Cobain and A. Einstein", "Donald E. Knuth and Kurt Cobain and"); + return Stream.of( + " Knuth, Donald E. ", + "Knuth, Donald E. and Kurt Cobain and A. Einstein", + ", and Kurt Cobain and A. Einstein", + "Donald E. Knuth and Kurt Cobain and ,", + "and Kurt Cobain and A. Einstein", + "Donald E. Knuth and Kurt Cobain and"); } } From 73f1ad5e55188fd5e198de971b27ef3851732069 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 3 Sep 2022 13:08:25 +0200 Subject: [PATCH 47/52] Fix parsing of JabRef v5.7 study.yml files (#9124) --- CHANGELOG.md | 3 ++- .../jabref/logic/crawler/StudyYamlParser.java | 5 ----- src/main/java/org/jabref/model/study/Study.java | 3 +++ .../logic/crawler/StudyYamlParserTest.java | 12 ++++++++++++ .../jabref/logic/crawler/study-jabref-5.7.yml | 17 +++++++++++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 src/test/resources/org/jabref/logic/crawler/study-jabref-5.7.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a0cfc8b3ac..762f29b556e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,8 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We call backup files `.bak` and temporary writing files now `.sav`. - JabRef keeps 10 older versions of a `.bib` file in the [user data dir](https://github.com/harawata/appdirs#supported-directories) (instead of a single `.sav` (now: `.bak`) file in the directory of the `.bib` file) - We changed the button label from "Return to JabRef" to "Return to library" to better indicate the purpose of the action. -- We removed "last-search-date" from the SLR feature, because the last-search-date can be deducted from the git logs. +- We removed "last-search-date" from the SLR feature, because the last-search-date can be deducted from the git logs. [#9116](https://github.com/JabRef/jabref/pull/9116) +- A user can now add arbitrary data into `study.yml`. JabRef just ignores this data. [#9124](https://github.com/JabRef/jabref/pull/9124) - We reworked the External Changes Resolver dialog. [#9021](https://github.com/JabRef/jabref/pull/9021) - We reworked the Define study parameters dialog. [#9123](https://github.com/JabRef/jabref/pull/9123) diff --git a/src/main/java/org/jabref/logic/crawler/StudyYamlParser.java b/src/main/java/org/jabref/logic/crawler/StudyYamlParser.java index df2138434d2..db1bb1b9a9f 100644 --- a/src/main/java/org/jabref/logic/crawler/StudyYamlParser.java +++ b/src/main/java/org/jabref/logic/crawler/StudyYamlParser.java @@ -8,10 +8,8 @@ import org.jabref.model.study.Study; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; public class StudyYamlParser { @@ -20,7 +18,6 @@ public class StudyYamlParser { */ public Study parseStudyYamlFile(Path studyYamlFile) throws IOException { ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); - yamlMapper.registerModule(new JavaTimeModule()); try (InputStream fileInputStream = new FileInputStream(studyYamlFile.toFile())) { return yamlMapper.readValue(fileInputStream, Study.class); } @@ -32,8 +29,6 @@ public Study parseStudyYamlFile(Path studyYamlFile) throws IOException { public void writeStudyYamlFile(Study study, Path studyYamlFile) throws IOException { ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER) .enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)); - yamlMapper.registerModule(new JavaTimeModule()); - yamlMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); yamlMapper.writeValue(studyYamlFile.toFile(), study); } } diff --git a/src/main/java/org/jabref/model/study/Study.java b/src/main/java/org/jabref/model/study/Study.java index 3748f0962bc..c9a416eda4e 100644 --- a/src/main/java/org/jabref/model/study/Study.java +++ b/src/main/java/org/jabref/model/study/Study.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @@ -12,6 +13,8 @@ * This class defines all aspects of a scientific study relevant to the application. It is a proxy for the file based study definition. */ @JsonPropertyOrder({"authors", "title", "research-questions", "queries", "databases"}) +// The user might add arbitrary content to the YAML +@JsonIgnoreProperties(ignoreUnknown = true) public class Study { private List authors; diff --git a/src/test/java/org/jabref/logic/crawler/StudyYamlParserTest.java b/src/test/java/org/jabref/logic/crawler/StudyYamlParserTest.java index 1b169f7f00a..d4e63f64bc1 100644 --- a/src/test/java/org/jabref/logic/crawler/StudyYamlParserTest.java +++ b/src/test/java/org/jabref/logic/crawler/StudyYamlParserTest.java @@ -18,6 +18,7 @@ class StudyYamlParserTest { @TempDir static Path testDirectory; + Study expectedStudy; @BeforeEach @@ -48,4 +49,15 @@ public void writeStudyFileSuccessfully() throws Exception { Study study = new StudyYamlParser().parseStudyYamlFile(testDirectory.resolve("study.yml")); assertEquals(expectedStudy, study); } + + @Test + public void readsJabRef57StudySuccessfully() throws Exception { + // The field "last-search-date" was removed + // If the field is "just" removed from the datamodel, one gets following exception: + // com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "last-search-date" (class org.jabref.model.study.Study), not marked as ignorable (5 known properties: "authors", "research-questions", "queries", "title", "databases"]) + // This tests ensures that this exception does not occur + URL studyDefinition = StudyYamlParser.class.getResource("study-jabref-5.7.yml"); + Study study = new StudyYamlParser().parseStudyYamlFile(Path.of(studyDefinition.toURI())); + assertEquals(expectedStudy, study); + } } diff --git a/src/test/resources/org/jabref/logic/crawler/study-jabref-5.7.yml b/src/test/resources/org/jabref/logic/crawler/study-jabref-5.7.yml new file mode 100644 index 00000000000..3b5b45bbb66 --- /dev/null +++ b/src/test/resources/org/jabref/logic/crawler/study-jabref-5.7.yml @@ -0,0 +1,17 @@ +authors: + - Jab Ref +title: TestStudyName +last-search-date: 2020-11-26 +research-questions: + - Question1 + - Question2 +queries: + - query: Quantum + - query: Cloud Computing + - query: '"Software Engineering"' +databases: + - name: Springer + - name: ArXiv + - name: Medline/PubMed + - name: IEEEXplore + enabled: false From e3ddb7c92a783b58735154ea98189e76d056b24e Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 3 Sep 2022 13:24:49 +0200 Subject: [PATCH 48/52] Compile fix --- src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java index c6c77eaaf31..bc2cb7ac859 100644 --- a/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java +++ b/src/main/java/org/jabref/gui/slr/StudyDatabaseItem.java @@ -62,7 +62,7 @@ public boolean equals(Object o) { return false; } StudyDatabaseItem that = (StudyDatabaseItem) o; - return Object.equals(getName(),that.getName()) && Object.equals(isEnabled(), that.isEnabled()); + return Objects.equals(getName(), that.getName()) && Objects.equals(isEnabled(), that.isEnabled()); } @Override From 069eedc7e95989c6c3aa728b7909d14013a77d5e Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 3 Sep 2022 14:08:31 +0200 Subject: [PATCH 49/52] fix l10n --- src/main/resources/l10n/JabRef_en.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index d020d8e5691..c560fc1b280 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2406,7 +2406,6 @@ Database=Database Databases=Databases Manage\ study\ definition=Manage study definition Add\ Author\:=Add Author\: -Select\ Databases\:=Select the databases that should be searched\: Add\ Query\:=Add Query\: Add\ Research\ Question\:=Add Research Question\: Perform\ search\ for\ existing\ systematic\ literature\ review=Perform search for existing systematic literature review @@ -2416,6 +2415,7 @@ Searching=Searching Start\ new\ systematic\ literature\ review=Start new systematic literature review Study\ Title\:=Study Title\: Study\ repository\ could\ not\ be\ created=Study repository could not be created +Select\ Databases\:=Select Databases: All\ query\ terms\ are\ joined\ using\ the\ logical\ AND,\ and\ OR\ operators=All query terms are joined using the logical AND, and OR operators Finalize=Finalize From 8b48e9632be9a2c2d6d2d327e5056ec21c537d98 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 3 Sep 2022 16:58:37 +0200 Subject: [PATCH 50/52] "study.yml" is static now (#9125) --- .../jabref/gui/slr/StartNewStudyAction.java | 3 ++- .../jabref/logic/crawler/StudyRepository.java | 22 +++++++++++-------- .../org/jabref/logic/git/SlrGitHandler.java | 4 +++- .../org/jabref/logic/crawler/CrawlerTest.java | 4 ++-- .../StudyDatabaseToFetcherConverterTest.java | 4 ++-- .../logic/crawler/StudyRepositoryTest.java | 4 ++-- .../logic/crawler/StudyYamlParserTest.java | 10 ++++----- 7 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/jabref/gui/slr/StartNewStudyAction.java b/src/main/java/org/jabref/gui/slr/StartNewStudyAction.java index 09a90666e2f..0bf2a4902c5 100644 --- a/src/main/java/org/jabref/gui/slr/StartNewStudyAction.java +++ b/src/main/java/org/jabref/gui/slr/StartNewStudyAction.java @@ -8,6 +8,7 @@ import org.jabref.gui.StateManager; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.TaskExecutor; +import org.jabref.logic.crawler.StudyRepository; import org.jabref.logic.crawler.StudyYamlParser; import org.jabref.model.study.Study; import org.jabref.model.util.FileUpdateMonitor; @@ -25,7 +26,7 @@ public StartNewStudyAction(JabRefFrame frame, FileUpdateMonitor fileUpdateMonito @Override protected void setupRepository(Path studyRepositoryRoot) throws IOException, GitAPIException { StudyYamlParser studyYAMLParser = new StudyYamlParser(); - studyYAMLParser.writeStudyYamlFile(newStudy, studyRepositoryRoot.resolve("study.yml")); + studyYAMLParser.writeStudyYamlFile(newStudy, studyRepositoryRoot.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); } @Override diff --git a/src/main/java/org/jabref/logic/crawler/StudyRepository.java b/src/main/java/org/jabref/logic/crawler/StudyRepository.java index 19fdd7e4abe..63feea3d825 100644 --- a/src/main/java/org/jabref/logic/crawler/StudyRepository.java +++ b/src/main/java/org/jabref/logic/crawler/StudyRepository.java @@ -48,9 +48,10 @@ * the structured persistence of the crawling results for the study within the file based repository, * as well as the sharing, and versioning of results using git. */ -class StudyRepository { +public class StudyRepository { // Tests work with study.yml - private static final String STUDY_DEFINITION_FILE_NAME = "study.yml"; + public static final String STUDY_DEFINITION_FILE_NAME = "study.yml"; + private static final Logger LOGGER = LoggerFactory.getLogger(StudyRepository.class); private static final Pattern MATCHCOLON = Pattern.compile(":"); private static final Pattern MATCHILLEGALCHARACTERS = Pattern.compile("[^A-Za-z0-9_.\\s=-]"); @@ -217,11 +218,8 @@ public Study getStudy() { */ public void persist(List crawlResults) throws IOException, GitAPIException, SaveException { updateWorkAndSearchBranch(); - persistStudy(); - gitHandler.createCommitOnCurrentBranch("Update search date", true); gitHandler.checkoutBranch(SEARCH_BRANCH); persistResults(crawlResults); - persistStudy(); try { // First commit changes to search branch and update remote String commitMessage = "Conducted search: " + LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); @@ -245,10 +243,15 @@ public void persist(List crawlResults) throws IOException, GitAPIEx */ private void updateRemoteSearchAndWorkBranch() throws IOException, GitAPIException { String currentBranch = gitHandler.getCurrentlyCheckedOutBranch(); + + // update remote search branch gitHandler.checkoutBranch(SEARCH_BRANCH); gitHandler.pushCommitsToRemoteRepository(); + + // update remote work branch gitHandler.checkoutBranch(WORK_BRANCH); gitHandler.pushCommitsToRemoteRepository(); + gitHandler.checkoutBranch(currentBranch); } @@ -258,15 +261,16 @@ private void updateRemoteSearchAndWorkBranch() throws IOException, GitAPIExcepti */ private void updateWorkAndSearchBranch() throws IOException, GitAPIException { String currentBranch = gitHandler.getCurrentlyCheckedOutBranch(); + + // update search branch gitHandler.checkoutBranch(SEARCH_BRANCH); gitHandler.pullOnCurrentBranch(); + + // update work branch gitHandler.checkoutBranch(WORK_BRANCH); gitHandler.pullOnCurrentBranch(); - gitHandler.checkoutBranch(currentBranch); - } - private void persistStudy() throws IOException { - new StudyYamlParser().writeStudyYamlFile(study, studyDefinitionFile); + gitHandler.checkoutBranch(currentBranch); } /** diff --git a/src/main/java/org/jabref/logic/git/SlrGitHandler.java b/src/main/java/org/jabref/logic/git/SlrGitHandler.java index d9bb027d220..334f4c7feec 100644 --- a/src/main/java/org/jabref/logic/git/SlrGitHandler.java +++ b/src/main/java/org/jabref/logic/git/SlrGitHandler.java @@ -12,6 +12,8 @@ import java.util.Optional; import java.util.StringJoiner; +import org.jabref.logic.crawler.StudyRepository; + import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.diff.DiffEntry; @@ -101,7 +103,7 @@ Map parsePatchForAddedEntries(String patch) throws IOException, Gi if (currentToken.startsWith("diff --git a/")) { // If the diff is related to a different file, save the diff for the previous file if (!(Objects.isNull(relativePath) || Objects.isNull(joiner))) { - if (!relativePath.contains("study.yml")) { + if (!relativePath.contains(StudyRepository.STUDY_DEFINITION_FILE_NAME)) { diffsPerFile.put(Path.of(repositoryPath.toString(), relativePath), joiner.toString()); } } diff --git a/src/test/java/org/jabref/logic/crawler/CrawlerTest.java b/src/test/java/org/jabref/logic/crawler/CrawlerTest.java index 7f2c60405cc..a16d3b4469d 100644 --- a/src/test/java/org/jabref/logic/crawler/CrawlerTest.java +++ b/src/test/java/org/jabref/logic/crawler/CrawlerTest.java @@ -120,8 +120,8 @@ private void setUpRepository() throws Exception { } private void setUpTestStudyDefinitionFile() throws Exception { - Path destination = tempRepositoryDirectory.resolve("study.yml"); - URL studyDefinition = this.getClass().getResource("study.yml"); + Path destination = tempRepositoryDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME); + URL studyDefinition = this.getClass().getResource(StudyRepository.STUDY_DEFINITION_FILE_NAME); FileUtil.copyFile(Path.of(studyDefinition.toURI()), destination, false); } } diff --git a/src/test/java/org/jabref/logic/crawler/StudyDatabaseToFetcherConverterTest.java b/src/test/java/org/jabref/logic/crawler/StudyDatabaseToFetcherConverterTest.java index 37829f6fb5d..78b557a6fe0 100644 --- a/src/test/java/org/jabref/logic/crawler/StudyDatabaseToFetcherConverterTest.java +++ b/src/test/java/org/jabref/logic/crawler/StudyDatabaseToFetcherConverterTest.java @@ -58,7 +58,7 @@ void setUpMocks() { @Test public void getActiveFetcherInstances() throws Exception { - Path studyDefinition = tempRepositoryDirectory.resolve("study.yml"); + Path studyDefinition = tempRepositoryDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME); copyTestStudyDefinitionFileIntoDirectory(studyDefinition); StudyRepository studyRepository = new StudyRepository( @@ -83,7 +83,7 @@ public void getActiveFetcherInstances() throws Exception { } private void copyTestStudyDefinitionFileIntoDirectory(Path destination) throws Exception { - URL studyDefinition = this.getClass().getResource("study.yml"); + URL studyDefinition = this.getClass().getResource(StudyRepository.STUDY_DEFINITION_FILE_NAME); FileUtil.copyFile(Path.of(studyDefinition.toURI()), destination, false); } } diff --git a/src/test/java/org/jabref/logic/crawler/StudyRepositoryTest.java b/src/test/java/org/jabref/logic/crawler/StudyRepositoryTest.java index 697b04958f6..5c6c14983d6 100644 --- a/src/test/java/org/jabref/logic/crawler/StudyRepositoryTest.java +++ b/src/test/java/org/jabref/logic/crawler/StudyRepositoryTest.java @@ -190,8 +190,8 @@ private StudyRepository getTestStudyRepository() throws Exception { * Copies the study definition file into the test repository */ private void setUpTestStudyDefinitionFile() throws Exception { - Path destination = tempRepositoryDirectory.resolve("study.yml"); - URL studyDefinition = this.getClass().getResource("study.yml"); + Path destination = tempRepositoryDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME); + URL studyDefinition = this.getClass().getResource(StudyRepository.STUDY_DEFINITION_FILE_NAME); FileUtil.copyFile(Path.of(studyDefinition.toURI()), destination, false); } diff --git a/src/test/java/org/jabref/logic/crawler/StudyYamlParserTest.java b/src/test/java/org/jabref/logic/crawler/StudyYamlParserTest.java index d4e63f64bc1..db2fb4f45e0 100644 --- a/src/test/java/org/jabref/logic/crawler/StudyYamlParserTest.java +++ b/src/test/java/org/jabref/logic/crawler/StudyYamlParserTest.java @@ -23,8 +23,8 @@ class StudyYamlParserTest { @BeforeEach void setupStudy() throws Exception { - Path destination = testDirectory.resolve("study.yml"); - URL studyDefinition = StudyYamlParser.class.getResource("study.yml"); + Path destination = testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME); + URL studyDefinition = StudyYamlParser.class.getResource(StudyRepository.STUDY_DEFINITION_FILE_NAME); FileUtil.copyFile(Path.of(studyDefinition.toURI()), destination, true); List authors = List.of("Jab Ref"); @@ -39,14 +39,14 @@ void setupStudy() throws Exception { @Test public void parseStudyFileSuccessfully() throws Exception { - Study study = new StudyYamlParser().parseStudyYamlFile(testDirectory.resolve("study.yml")); + Study study = new StudyYamlParser().parseStudyYamlFile(testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); assertEquals(expectedStudy, study); } @Test public void writeStudyFileSuccessfully() throws Exception { - new StudyYamlParser().writeStudyYamlFile(expectedStudy, testDirectory.resolve("study.yml")); - Study study = new StudyYamlParser().parseStudyYamlFile(testDirectory.resolve("study.yml")); + new StudyYamlParser().writeStudyYamlFile(expectedStudy, testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); + Study study = new StudyYamlParser().parseStudyYamlFile(testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); assertEquals(expectedStudy, study); } From 852f5c7917803f3c27ff05944b84c2dd05e062ea Mon Sep 17 00:00:00 2001 From: Houssem Nasri Date: Sat, 3 Sep 2022 20:51:21 +0100 Subject: [PATCH 51/52] Don't show the info button when the authors field content is identical (#9128) --- .../mergeentries/newmergedialog/PersonsNameFieldRowView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/PersonsNameFieldRowView.java b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/PersonsNameFieldRowView.java index e42bb91743b..8d707f34b0f 100644 --- a/src/main/java/org/jabref/gui/mergeentries/newmergedialog/PersonsNameFieldRowView.java +++ b/src/main/java/org/jabref/gui/mergeentries/newmergedialog/PersonsNameFieldRowView.java @@ -21,7 +21,7 @@ public PersonsNameFieldRowView(Field field, BibEntry leftEntry, BibEntry rightEn leftEntryNames = authorsParser.parse(viewModel.getLeftFieldValue()); rightEntryNames = authorsParser.parse(viewModel.getRightFieldValue()); - if (!leftEntry.equals(rightEntry) && leftEntryNames.equals(rightEntryNames)) { + if (!viewModel.hasEqualLeftAndRightValues() && leftEntryNames.equals(rightEntryNames)) { showPersonsNamesAreTheSameInfo(); shouldShowDiffs.set(false); } From 10fae1b462daddc3dba39b4ce7b27270dc5a3e2e Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 3 Sep 2022 22:08:01 +0200 Subject: [PATCH 52/52] Enable files/files Co-authored-by: Christoph --- .../java/org/jabref/model/util/FileHelper.java | 16 ++++++++++++---- .../org/jabref/model/util/FileHelperTest.java | 9 +++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/jabref/model/util/FileHelper.java b/src/main/java/org/jabref/model/util/FileHelper.java index c844b584718..19df95ad417 100644 --- a/src/main/java/org/jabref/model/util/FileHelper.java +++ b/src/main/java/org/jabref/model/util/FileHelper.java @@ -151,8 +151,12 @@ public static boolean isCharLegal(char c) { } /** - * Converts a relative filename to an absolute one, if necessary. Returns - * an empty optional if the file does not exist. + * Converts a relative filename to an absolute one, if necessary. + * + * @param fileName the filename (e.g., a .pdf file), may contain path separators + * @param directory the directory which should be search starting point + * + * @returns an empty optional if the file does not exist, otherwise, the absolute path */ public static Optional find(String fileName, Path directory) { Objects.requireNonNull(fileName); @@ -166,11 +170,15 @@ public static Optional find(String fileName, Path directory) { if (fileName.isEmpty()) { return Optional.of(directory); } + + Path resolvedFile = directory.resolve(fileName); + if (Files.exists(resolvedFile)) { + return Optional.of(resolvedFile); + } + // get the furthest path element from root and check if our filename starts with the same name // workaround for old JabRef behavior String furthestDirFromRoot = directory.getFileName().toString(); - Path resolvedFile = directory.resolve(fileName); - if (fileName.startsWith(furthestDirFromRoot)) { resolvedFile = directory.resolveSibling(fileName); } diff --git a/src/test/java/org/jabref/model/util/FileHelperTest.java b/src/test/java/org/jabref/model/util/FileHelperTest.java index a3e0d325a93..01bd79a00b4 100644 --- a/src/test/java/org/jabref/model/util/FileHelperTest.java +++ b/src/test/java/org/jabref/model/util/FileHelperTest.java @@ -58,10 +58,11 @@ public void testFindsFileStartingWithTheSameDirectory(@TempDir Path temp) throws @Test public void testDoesNotFindsFileStartingWithTheSameDirectoryHasASubdirectory(@TempDir Path temp) throws Exception { - Path firstFilePath = temp.resolve("files"); - Path secondFilesPath = firstFilePath.resolve("files"); + Path firstFilesPath = temp.resolve("files"); + Path secondFilesPath = firstFilesPath.resolve("files"); Files.createDirectories(secondFilesPath); - Path firstFile = Files.createFile(secondFilesPath.resolve("test.pdf")); - assertEquals(Optional.empty(), FileHelper.find("files/test.pdf", temp.resolve("files"))); + Path testFile = secondFilesPath.resolve("test.pdf"); + Files.createFile(testFile); + assertEquals(Optional.of(testFile.toAbsolutePath()), FileHelper.find("files/test.pdf", firstFilesPath)); } }