diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index adaa4aa1b3d..9dd77f1c5b8 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -26,7 +26,6 @@ import org.jabref.logic.exporter.Exporter; import org.jabref.logic.exporter.ExporterFactory; import org.jabref.logic.exporter.SavePreferences; -import org.jabref.logic.exporter.TemplateExporter; import org.jabref.logic.exporter.XmpPdfExporter; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.ImportException; @@ -40,7 +39,6 @@ import org.jabref.logic.importer.WebFetchers; import org.jabref.logic.importer.fileformat.BibtexParser; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.net.URLDownload; import org.jabref.logic.search.DatabaseSearcher; import org.jabref.logic.search.SearchQuery; @@ -74,10 +72,11 @@ public class ArgumentProcessor { private boolean noGUINeeded; public ArgumentProcessor(String[] args, Mode startupMode, PreferencesService preferencesService) throws org.apache.commons.cli.ParseException { - cli = new JabRefCLI(args); + this.cli = new JabRefCLI(args); this.startupMode = startupMode; this.preferencesService = preferencesService; - parserResults = processArguments(); + + this.parserResults = processArguments(); } /** @@ -186,7 +185,7 @@ private List processArguments() { } if ((startupMode == Mode.INITIAL_START) && cli.isHelp()) { - JabRefCLI.printUsage(); + JabRefCLI.printUsage(preferencesService); noGUINeeded = true; return Collections.emptyList(); } @@ -399,14 +398,18 @@ private boolean exportMatches(List loaded) { } // export new database - Optional exporter = Globals.exportFactory.getExporterByName(formatName); + ExporterFactory exporterFactory = ExporterFactory.create( + preferencesService, + Globals.entryTypesManager, + Globals.journalAbbreviationRepository); + Optional exporter = exporterFactory.getExporterByName(formatName); if (exporter.isEmpty()) { System.err.println(Localization.lang("Unknown export format") + ": " + formatName); } else { // We have an TemplateExporter instance: try { System.out.println(Localization.lang("Exporting") + ": " + data[1]); - exporter.get().export(databaseContext, Path.of(data[1]), matches); + exporter.get().export(databaseContext, Path.of(data[1]), matches, Collections.emptyList()); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[1] + "': " + Throwables.getStackTraceAsString(ex)); @@ -561,23 +564,27 @@ private void exportFile(List loaded, String[] data) { // format to the given file. ParserResult pr = loaded.get(loaded.size() - 1); - // Set the global variable for this database's file directory before exporting, - // so formatters can resolve linked files correctly. - // (This is an ugly hack!) Path path = pr.getPath().get().toAbsolutePath(); BibDatabaseContext databaseContext = pr.getDatabaseContext(); databaseContext.setDatabasePath(path); - Globals.prefs.fileDirForDatabase = databaseContext + List fileDirForDatabase = databaseContext .getFileDirectories(preferencesService.getFilePreferences()); System.out.println(Localization.lang("Exporting") + ": " + data[0]); - Optional exporter = Globals.exportFactory.getExporterByName(data[1]); + ExporterFactory exporterFactory = ExporterFactory.create( + preferencesService, + Globals.entryTypesManager, + Globals.journalAbbreviationRepository); + Optional exporter = exporterFactory.getExporterByName(data[1]); if (exporter.isEmpty()) { System.err.println(Localization.lang("Unknown export format") + ": " + data[1]); } else { // We have an exporter: try { - exporter.get().export(pr.getDatabaseContext(), Path.of(data[0]), - pr.getDatabaseContext().getDatabase().getEntries()); + exporter.get().export( + pr.getDatabaseContext(), + Path.of(data[0]), + pr.getDatabaseContext().getDatabase().getEntries(), + fileDirForDatabase); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[0] + "': " + Throwables.getStackTraceAsString(ex)); @@ -591,20 +598,6 @@ private void importPreferences() { preferencesService.importPreferences(Path.of(cli.getPreferencesImport())); Globals.entryTypesManager.addCustomOrModifiedTypes(preferencesService.getBibEntryTypes(BibDatabaseMode.BIBTEX), preferencesService.getBibEntryTypes(BibDatabaseMode.BIBLATEX)); - List customExporters = - preferencesService.getCustomExportFormats(Globals.journalAbbreviationRepository); - LayoutFormatterPreferences layoutPreferences = - preferencesService.getLayoutFormatterPreferences(Globals.journalAbbreviationRepository); - SavePreferences savePreferences = preferencesService.getSavePreferencesForExport(); - XmpPreferences xmpPreferences = preferencesService.getXmpPreferences(); - BibDatabaseMode bibDatabaseMode = preferencesService.getGeneralPreferences().getDefaultBibDatabaseMode(); - Globals.exportFactory = ExporterFactory.create( - customExporters, - layoutPreferences, - savePreferences, - xmpPreferences, - bibDatabaseMode, - Globals.entryTypesManager); } catch (JabRefException ex) { LOGGER.error("Cannot import preferences", ex); } diff --git a/src/main/java/org/jabref/cli/JabRefCLI.java b/src/main/java/org/jabref/cli/JabRefCLI.java index 720ea0290aa..367c929541e 100644 --- a/src/main/java/org/jabref/cli/JabRefCLI.java +++ b/src/main/java/org/jabref/cli/JabRefCLI.java @@ -3,7 +3,10 @@ import java.util.List; import org.jabref.gui.Globals; +import org.jabref.logic.exporter.Exporter; +import org.jabref.logic.exporter.ExporterFactory; import org.jabref.logic.l10n.Localization; +import org.jabref.preferences.PreferencesService; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; @@ -11,13 +14,11 @@ import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class JabRefCLI { + private static final int WIDTH = 100; // Number of characters per line before a line break must be added. + private static final String WRAPPED_LINE_PREFIX = ""; // If a line break is added, this prefix will be inserted at the beginning of the next line - private static final int WIDTH = 100; // Number of characters per line - private static final Logger LOGGER = LoggerFactory.getLogger(JabRefCLI.class); private final CommandLine cl; private final List leftOver; @@ -47,10 +48,6 @@ public boolean isBlank() { return cl.hasOption("blank"); } - public boolean isLoadSession() { - return cl.hasOption("loads"); - } - public boolean isDisableGui() { return cl.hasOption("nogui"); } @@ -291,14 +288,19 @@ public void displayVersion() { System.out.println(getVersionInfo()); } - public static void printUsage() { + public static void printUsage(PreferencesService preferencesService) { String header = ""; String importFormats = Globals.IMPORT_FORMAT_READER.getImportFormatList(); String importFormatsList = String.format("%s:%n%s%n", Localization.lang("Available import formats"), importFormats); - String outFormats = Globals.exportFactory.getExportersAsString(70, 20, ""); - String outFormatsList = String.format("%s: %s%n", Localization.lang("Available export formats"), outFormats); + ExporterFactory exporterFactory = ExporterFactory.create( + preferencesService, + Globals.entryTypesManager, + Globals.journalAbbreviationRepository); + String outFormatsIntro = Localization.lang("Available export formats"); + String outFormats = wrapStringList(exporterFactory.getExporters().stream().map(Exporter::getId).toList(), outFormatsIntro.length()); + String outFormatsList = String.format("%s: %s%n", outFormatsIntro, outFormats); String footer = '\n' + importFormatsList + outFormatsList + "\nPlease report issues at https://github.com/JabRef/jabref/issues."; @@ -313,4 +315,25 @@ private String getVersionInfo() { public List getLeftOver() { return leftOver; } + + /** + * Creates and wraps a multi-line and colon-seperated string from a List of Strings. + */ + protected static String wrapStringList(List list, int firstLineIntroLength) { + StringBuilder builder = new StringBuilder(); + int lastBreak = -firstLineIntroLength; + + for (String line : list) { + if (((builder.length() + 2 + line.length()) - lastBreak) > WIDTH) { + builder.append(",\n"); + lastBreak = builder.length(); + builder.append(WRAPPED_LINE_PREFIX); + } else if (builder.length() > 0) { + builder.append(", "); + } + builder.append(line); + } + + return builder.toString(); + } } diff --git a/src/main/java/org/jabref/cli/Launcher.java b/src/main/java/org/jabref/cli/Launcher.java index fb49340b5a7..1b20af32edb 100644 --- a/src/main/java/org/jabref/cli/Launcher.java +++ b/src/main/java/org/jabref/cli/Launcher.java @@ -11,7 +11,6 @@ import org.jabref.gui.Globals; import org.jabref.gui.MainApplication; -import org.jabref.logic.exporter.ExporterFactory; import org.jabref.logic.journals.JournalAbbreviationLoader; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.ProxyAuthenticator; @@ -78,7 +77,7 @@ public static void main(String[] args) { MainApplication.main(argumentProcessor.getParserResults(), argumentProcessor.isBlank(), preferences, ARGUMENTS); } catch (ParseException e) { LOGGER.error("Problem parsing arguments", e); - JabRefCLI.printUsage(); + JabRefCLI.printUsage(preferences); } } catch (Exception ex) { LOGGER.error("Unexpected exception", ex); @@ -151,13 +150,6 @@ private static void applyPreferences(PreferencesService preferences) { Globals.entryTypesManager.addCustomOrModifiedTypes( preferences.getBibEntryTypes(BibDatabaseMode.BIBTEX), preferences.getBibEntryTypes(BibDatabaseMode.BIBLATEX)); - Globals.exportFactory = ExporterFactory.create( - preferences.getCustomExportFormats(Globals.journalAbbreviationRepository), - preferences.getLayoutFormatterPreferences(Globals.journalAbbreviationRepository), - preferences.getSavePreferencesForExport(), - preferences.getXmpPreferences(), - preferences.getGeneralPreferences().getDefaultBibDatabaseMode(), - Globals.entryTypesManager); // Initialize protected terms loader Globals.protectedTermsLoader = new ProtectedTermsLoader(preferences.getProtectedTermsPreferences()); diff --git a/src/main/java/org/jabref/gui/Globals.java b/src/main/java/org/jabref/gui/Globals.java index 0e575e8a6bd..6070283d1d1 100644 --- a/src/main/java/org/jabref/gui/Globals.java +++ b/src/main/java/org/jabref/gui/Globals.java @@ -13,7 +13,6 @@ import org.jabref.gui.util.DefaultFileUpdateMonitor; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.TaskExecutor; -import org.jabref.logic.exporter.ExporterFactory; import org.jabref.logic.importer.ImportFormatReader; import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.protectedterms.ProtectedTermsLoader; @@ -71,7 +70,6 @@ public class Globals { */ public static ProtectedTermsLoader protectedTermsLoader; - public static ExporterFactory exportFactory; public static CountingUndoManager undoManager = new CountingUndoManager(); public static BibEntryTypesManager entryTypesManager = new BibEntryTypesManager(); diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 5abadc9423e..4e22884c71b 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -816,7 +816,7 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new CopyMoreAction(StandardActions.COPY_KEY_AND_TITLE, dialogService, stateManager, Globals.getClipboardManager(), prefs)), factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new CopyMoreAction(StandardActions.COPY_KEY_AND_LINK, dialogService, stateManager, Globals.getClipboardManager(), prefs)), factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, Globals.getClipboardManager(), Globals.TASK_EXECUTOR, prefs.getPreviewPreferences())), - factory.createMenuItem(StandardActions.EXPORT_SELECTED_TO_CLIPBOARD, new ExportToClipboardAction(dialogService, Globals.exportFactory, stateManager, Globals.getClipboardManager(), Globals.TASK_EXECUTOR, prefs))), + factory.createMenuItem(StandardActions.EXPORT_SELECTED_TO_CLIPBOARD, new ExportToClipboardAction(dialogService, stateManager, Globals.getClipboardManager(), Globals.TASK_EXECUTOR, prefs))), factory.createMenuItem(StandardActions.PASTE, new EditAction(StandardActions.PASTE, this, stateManager)), diff --git a/src/main/java/org/jabref/gui/exporter/ExportCommand.java b/src/main/java/org/jabref/gui/exporter/ExportCommand.java index f3c6812a764..c5479d8c2cd 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportCommand.java +++ b/src/main/java/org/jabref/gui/exporter/ExportCommand.java @@ -24,12 +24,8 @@ import org.jabref.gui.util.FileFilterConverter; import org.jabref.logic.exporter.Exporter; import org.jabref.logic.exporter.ExporterFactory; -import org.jabref.logic.exporter.SavePreferences; -import org.jabref.logic.exporter.TemplateExporter; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.util.io.FileUtil; -import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.preferences.PreferencesService; @@ -71,18 +67,15 @@ public ExportCommand(ExportMethod exportMethod, @Override public void execute() { - List customExporters = preferences.getCustomExportFormats(Globals.journalAbbreviationRepository); - LayoutFormatterPreferences layoutPreferences = preferences.getLayoutFormatterPreferences(Globals.journalAbbreviationRepository); - SavePreferences savePreferences = preferences.getSavePreferencesForExport(); - XmpPreferences xmpPreferences = preferences.getXmpPreferences(); - // Get list of exporters and sort before adding to file dialog - List exporters = Globals.exportFactory.getExporters().stream() - .sorted(Comparator.comparing(Exporter::getName)) - .collect(Collectors.toList()); + ExporterFactory exporterFactory = ExporterFactory.create( + preferences, + Globals.entryTypesManager, + Globals.journalAbbreviationRepository); + List exporters = exporterFactory.getExporters().stream() + .sorted(Comparator.comparing(Exporter::getName)) + .collect(Collectors.toList()); - Globals.exportFactory = ExporterFactory.create(customExporters, layoutPreferences, savePreferences, - xmpPreferences, preferences.getGeneralPreferences().getDefaultBibDatabaseMode(), Globals.entryTypesManager); FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .addExtensionFilter(FileFilterConverter.exporterToExtensionFilter(exporters)) .withDefaultExtension(preferences.getImportExportPreferences().getLastExportExtension()) @@ -111,10 +104,7 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt .orElse(Collections.emptyList()); } - // Set the global variable for this database's file directory before exporting, - // so formatters can resolve linked files correctly. - // (This is an ugly hack!) - Globals.prefs.fileDirForDatabase = stateManager.getActiveDatabase() + List fileDirForDatabase = stateManager.getActiveDatabase() .map(db -> db.getFileDirectories(preferences.getFilePreferences())) .orElse(List.of(preferences.getFilePreferences().getWorkingDirectory())); @@ -129,7 +119,8 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt .wrap(() -> { format.export(stateManager.getActiveDatabase().get(), file, - finEntries); + finEntries, + fileDirForDatabase); return null; // can not use BackgroundTask.wrap(Runnable) because Runnable.run() can't throw Exceptions }) .onSuccess(save -> { diff --git a/src/main/java/org/jabref/gui/exporter/ExportToClipboardAction.java b/src/main/java/org/jabref/gui/exporter/ExportToClipboardAction.java index 1bf864a1c76..79a044aef28 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportToClipboardAction.java +++ b/src/main/java/org/jabref/gui/exporter/ExportToClipboardAction.java @@ -14,6 +14,7 @@ import org.jabref.gui.ClipBoardManager; import org.jabref.gui.DialogService; +import org.jabref.gui.Globals; import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; @@ -46,23 +47,20 @@ public class ExportToClipboardAction extends SimpleCommand { private final DialogService dialogService; private final List entries = new ArrayList<>(); - private final ExporterFactory exporterFactory; private final ClipBoardManager clipBoardManager; private final TaskExecutor taskExecutor; private final PreferencesService preferences; private final StateManager stateManager; public ExportToClipboardAction(DialogService dialogService, - ExporterFactory exporterFactory, StateManager stateManager, ClipBoardManager clipBoardManager, TaskExecutor taskExecutor, - PreferencesService prefs) { + PreferencesService preferencesService) { this.dialogService = dialogService; - this.exporterFactory = exporterFactory; this.clipBoardManager = clipBoardManager; this.taskExecutor = taskExecutor; - this.preferences = prefs; + this.preferences = preferencesService; this.stateManager = stateManager; this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); @@ -75,6 +73,10 @@ public void execute() { return; } + ExporterFactory exporterFactory = ExporterFactory.create( + preferences, + Globals.entryTypesManager, + Globals.journalAbbreviationRepository); List exporters = exporterFactory.getExporters().stream() .sorted(Comparator.comparing(Exporter::getName)) .filter(exporter -> SUPPORTED_FILETYPES.contains(exporter.getFileType())) @@ -100,12 +102,9 @@ public void execute() { } private ExportResult exportToClipboard(Exporter exporter) throws Exception { - // Set the global variable for this database's file directory before exporting, - // so formatters can resolve linked files correctly. - // (This is an ugly hack!) - preferences.storeFileDirForDatabase(stateManager.getActiveDatabase() - .map(db -> db.getFileDirectories(preferences.getFilePreferences())) - .orElse(List.of(preferences.getFilePreferences().getWorkingDirectory()))); + List fileDirForDatabase = stateManager.getActiveDatabase() + .map(db -> db.getFileDirectories(preferences.getFilePreferences())) + .orElse(List.of(preferences.getFilePreferences().getWorkingDirectory())); // Add chosen export type to last used preference, to become default preferences.getImportExportPreferences().setLastExportExtension(exporter.getName()); @@ -119,8 +118,7 @@ private ExportResult exportToClipboard(Exporter exporter) throws Exception { entries.addAll(stateManager.getSelectedEntries()); // Write to file: - exporter.export(stateManager.getActiveDatabase().get(), tmp, - entries); + exporter.export(stateManager.getActiveDatabase().get(), tmp, entries, fileDirForDatabase); // Read the file and put the contents on the clipboard: return new ExportResult(Files.readString(tmp), exporter.getFileType()); diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index 00e59daaa08..5031113a46d 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -8,7 +8,6 @@ import org.jabref.gui.ClipBoardManager; import org.jabref.gui.DialogService; -import org.jabref.gui.Globals; import org.jabref.gui.LibraryTab; import org.jabref.gui.SendAsEMailAction; import org.jabref.gui.StateManager; @@ -116,7 +115,7 @@ private static Menu createCopySubMenu(ActionFactory factory, copySpecialMenu.getItems().addAll( new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.EXPORT_TO_CLIPBOARD, new ExportToClipboardAction(dialogService, Globals.exportFactory, stateManager, clipBoardManager, taskExecutor, preferencesService))); + factory.createMenuItem(StandardActions.EXPORT_TO_CLIPBOARD, new ExportToClipboardAction(dialogService, stateManager, clipBoardManager, taskExecutor, preferencesService))); return copySpecialMenu; } diff --git a/src/main/java/org/jabref/gui/preferences/PreferencesDialogViewModel.java b/src/main/java/org/jabref/gui/preferences/PreferencesDialogViewModel.java index 56b938f9194..2feaa0d494b 100644 --- a/src/main/java/org/jabref/gui/preferences/PreferencesDialogViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/PreferencesDialogViewModel.java @@ -10,7 +10,6 @@ import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; -import org.jabref.gui.Globals; import org.jabref.gui.JabRefFrame; import org.jabref.gui.preferences.appearance.AppearanceTab; import org.jabref.gui.preferences.citationkeypattern.CitationKeyPatternTab; @@ -36,10 +35,7 @@ import org.jabref.gui.preferences.xmp.XmpPrivacyTab; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.JabRefException; -import org.jabref.logic.exporter.ExporterFactory; -import org.jabref.logic.exporter.TemplateExporter; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.util.StandardFileType; import org.jabref.preferences.PreferencesFilter; import org.jabref.preferences.PreferencesService; @@ -95,7 +91,7 @@ public void importPreferences() { FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .addExtensionFilter(StandardFileType.XML) .withDefaultExtension(StandardFileType.XML) - .withInitialDirectory(preferences.getLastPreferencesExportPath()).build(); + .withInitialDirectory(preferences.getInternalPreferences().getLastPreferencesExportPath()).build(); dialogService.showFileOpenDialog(fileDialogConfiguration) .ifPresent(file -> { @@ -116,7 +112,7 @@ public void exportPreferences() { FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .addExtensionFilter(StandardFileType.XML) .withDefaultExtension(StandardFileType.XML) - .withInitialDirectory(preferences.getLastPreferencesExportPath()) + .withInitialDirectory(preferences.getInternalPreferences().getLastPreferencesExportPath()) .build(); dialogService.showFileSaveDialog(fileDialogConfiguration) @@ -124,7 +120,7 @@ public void exportPreferences() { try { storeAllSettings(); preferences.exportPreferences(exportFile); - preferences.storeLastPreferencesExportPath(exportFile); + preferences.getInternalPreferences().setLastPreferencesExportPath(exportFile); } catch (JabRefException ex) { LOGGER.warn(ex.getMessage(), ex); dialogService.showErrorDialogAndWait(Localization.lang("Export preferences"), ex); @@ -166,16 +162,6 @@ private void updateAfterPreferenceChanges() { setValues(); - List customExporters = preferences.getCustomExportFormats(Globals.journalAbbreviationRepository); - LayoutFormatterPreferences layoutPreferences = preferences.getLayoutFormatterPreferences(Globals.journalAbbreviationRepository); - Globals.exportFactory = ExporterFactory.create( - customExporters, - layoutPreferences, - preferences.getSavePreferencesForExport(), - preferences.getXmpPreferences(), - preferences.getGeneralPreferences().getDefaultBibDatabaseMode(), - Globals.entryTypesManager); - frame.getLibraryTabs().forEach(panel -> panel.getMainTable().getTableModel().refresh()); } diff --git a/src/main/java/org/jabref/gui/preferences/appearance/AppearanceTabViewModel.java b/src/main/java/org/jabref/gui/preferences/appearance/AppearanceTabViewModel.java index 8ea43197c97..e122a4732d6 100644 --- a/src/main/java/org/jabref/gui/preferences/appearance/AppearanceTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/appearance/AppearanceTabViewModel.java @@ -164,7 +164,7 @@ public void importCSSFile() { FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .addExtensionFilter(StandardFileType.CSS) .withDefaultExtension(StandardFileType.CSS) - .withInitialDirectory(preferences.getLastPreferencesExportPath()).build(); + .withInitialDirectory(preferences.getInternalPreferences().getLastPreferencesExportPath()).build(); dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(file -> customPathToThemeProperty.setValue(file.toAbsolutePath().toString())); diff --git a/src/main/java/org/jabref/logic/exporter/Exporter.java b/src/main/java/org/jabref/logic/exporter/Exporter.java index fb2f1267b3f..6fdfe20accb 100644 --- a/src/main/java/org/jabref/logic/exporter/Exporter.java +++ b/src/main/java/org/jabref/logic/exporter/Exporter.java @@ -2,7 +2,7 @@ import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -60,6 +60,10 @@ public String toString() { */ public abstract void export(BibDatabaseContext databaseContext, Path file, List entries) throws Exception; + public void export(BibDatabaseContext databaseContext, Path file, List entries, List fileDirForDatabase) throws Exception { + export(databaseContext, file, entries); + } + /** * Exports to all files linked to a given entry * @@ -77,7 +81,7 @@ public boolean exportToAllFilesOfEntry(BibDatabaseContext databaseContext, FileP if (file.getFileType().equals(fileType.getName())) { Optional filePath = file.findIn(databaseContext, filePreferences); if (filePath.isPresent()) { - export(databaseContext, filePath.get(), entriesToWrite); + export(databaseContext, filePath.get(), entriesToWrite, Collections.emptyList()); writtenToAFile = true; } } @@ -108,8 +112,8 @@ public boolean exportToFileByPath(BibDatabaseContext databaseContext, BibDatabas for (LinkedFile linkedFile : entry.getFiles()) { if (linkedFile.getFileType().equals(fileType.getName())) { Optional linkedFilePath = linkedFile.findIn(databaseContext.getFileDirectories(filePreferences)); - if (!linkedFilePath.isEmpty() && Files.exists(linkedFilePath.get()) && Files.isSameFile(linkedFilePath.get(), filePath)) { - export(databaseContext, filePath, Arrays.asList((entry))); + if (linkedFilePath.isPresent() && Files.exists(linkedFilePath.get()) && Files.isSameFile(linkedFilePath.get(), filePath)) { + export(databaseContext, filePath, List.of(entry), Collections.emptyList()); writtenABibEntry = true; } } diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index 0bdc3420238..407fec5ce5c 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -6,12 +6,14 @@ import java.util.Objects; import java.util.Optional; +import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.util.StandardFileType; import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntryTypesManager; +import org.jabref.preferences.PreferencesService; public class ExporterFactory { @@ -28,6 +30,18 @@ private ExporterFactory(List exporters) { this.exporters = Objects.requireNonNull(exporters); } + public static ExporterFactory create(PreferencesService preferencesService, + BibEntryTypesManager entryTypesManager, + JournalAbbreviationRepository abbreviationRepository) { + return ExporterFactory.create( + preferencesService.getCustomExportFormats(abbreviationRepository), + preferencesService.getLayoutFormatterPreferences(abbreviationRepository), + preferencesService.getSavePreferencesForExport(), + preferencesService.getXmpPreferences(), + preferencesService.getGeneralPreferences().getDefaultBibDatabaseMode(), + entryTypesManager); + } + public static ExporterFactory create(List customFormats, LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, @@ -72,32 +86,6 @@ public static ExporterFactory create(List customFormats, return new ExporterFactory(exporters); } - /** - * Build a string listing of all available exporters. - * - * @param maxLineLength The max line length before a line break must be added. - * @param linePrefix If a line break is added, this prefix will be inserted at the beginning of the next line. - * @return The string describing available exporters. - */ - public String getExportersAsString(int maxLineLength, int firstLineSubtraction, String linePrefix) { - StringBuilder builder = new StringBuilder(); - int lastBreak = -firstLineSubtraction; - - for (Exporter exporter : exporters) { - String name = exporter.getId(); - if (((builder.length() + 2 + name.length()) - lastBreak) > maxLineLength) { - builder.append(",\n"); - lastBreak = builder.length(); - builder.append(linePrefix); - } else if (builder.length() > 0) { - builder.append(", "); - } - builder.append(name); - } - - return builder.toString(); - } - /** * Get a list of all exporters. * diff --git a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java index a95265c7df0..44c751661cc 100644 --- a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java +++ b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java @@ -10,6 +10,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -176,8 +177,15 @@ private Reader getReader(String filename) throws IOException { } @Override - public void export(final BibDatabaseContext databaseContext, final Path file, - List entries) throws Exception { + public void export(BibDatabaseContext databaseContext, Path file, List entries) throws Exception { + export(databaseContext, file, entries, Collections.emptyList()); + } + + @Override + public void export(final BibDatabaseContext databaseContext, + final Path file, + List entries, + List fileDirForDatabase) throws Exception { Objects.requireNonNull(databaseContext); Objects.requireNonNull(entries); @@ -198,7 +206,7 @@ public void export(final BibDatabaseContext databaseContext, final Path file, // Print header try (Reader reader = getReader(lfFileName + BEGIN_INFIX + LAYOUT_EXTENSION)) { - LayoutHelper layoutHelper = new LayoutHelper(reader, layoutPreferences); + LayoutHelper layoutHelper = new LayoutHelper(reader, fileDirForDatabase, layoutPreferences); beginLayout = layoutHelper.getLayoutFromText(); } catch (IOException ex) { // If an exception was cast, export filter doesn't have a begin @@ -223,7 +231,7 @@ public void export(final BibDatabaseContext databaseContext, final Path file, Layout defLayout; LayoutHelper layoutHelper; try (Reader reader = getReader(lfFileName + LAYOUT_EXTENSION)) { - layoutHelper = new LayoutHelper(reader, layoutPreferences); + layoutHelper = new LayoutHelper(reader, fileDirForDatabase, layoutPreferences); defLayout = layoutHelper.getLayoutFromText(); } if (defLayout != null) { @@ -245,7 +253,7 @@ public void export(final BibDatabaseContext databaseContext, final Path file, } else { try (Reader reader = getReader(lfFileName + '.' + type.getName() + LAYOUT_EXTENSION)) { // We try to get a type-specific layout for this entry. - layoutHelper = new LayoutHelper(reader, layoutPreferences); + layoutHelper = new LayoutHelper(reader, fileDirForDatabase, layoutPreferences); layout = layoutHelper.getLayoutFromText(); layouts.put(type, layout); if (layout != null) { @@ -275,10 +283,9 @@ public void export(final BibDatabaseContext databaseContext, final Path file, } // Print footer - // changed section - begin (arudert) Layout endLayout = null; try (Reader reader = getReader(lfFileName + END_INFIX + LAYOUT_EXTENSION)) { - layoutHelper = new LayoutHelper(reader, layoutPreferences); + layoutHelper = new LayoutHelper(reader, fileDirForDatabase, layoutPreferences); endLayout = layoutHelper.getLayoutFromText(); } catch (IOException ex) { // If an exception was thrown, export filter doesn't have an end @@ -295,9 +302,7 @@ public void export(final BibDatabaseContext databaseContext, final Path file, layoutPreferences.clearCustomExportNameFormatters(); if (!missingFormatters.isEmpty() && LOGGER.isWarnEnabled()) { - StringBuilder sb = new StringBuilder("The following formatters could not be found: "); - sb.append(String.join(", ", missingFormatters)); - LOGGER.warn("Formatters {} not found", sb.toString()); + LOGGER.warn("Formatters {} not found", String.join(", ", missingFormatters)); } } } diff --git a/src/main/java/org/jabref/logic/layout/Layout.java b/src/main/java/org/jabref/logic/layout/Layout.java index 25ed99711d1..ea566fbe510 100644 --- a/src/main/java/org/jabref/logic/layout/Layout.java +++ b/src/main/java/org/jabref/logic/layout/Layout.java @@ -1,6 +1,7 @@ package org.jabref.logic.layout; import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -20,7 +21,7 @@ public class Layout { private final List missingFormatters = new ArrayList<>(); - public Layout(List parsedEntries, LayoutFormatterPreferences prefs) { + public Layout(List parsedEntries, List fileDirForDatabase, LayoutFormatterPreferences prefs) { List tmpEntries = new ArrayList<>(parsedEntries.size()); List blockEntries = null; @@ -46,6 +47,7 @@ public Layout(List parsedEntries, LayoutFormatterPreferences prefs) { blockEntries.add(parsedEntry); le = new LayoutEntry(blockEntries, parsedEntry.i == LayoutHelper.IS_FIELD_END ? LayoutHelper.IS_FIELD_START : LayoutHelper.IS_GROUP_START, + fileDirForDatabase, prefs); tmpEntries.add(le); blockEntries = null; @@ -61,7 +63,7 @@ public Layout(List parsedEntries, LayoutFormatterPreferences prefs) { } if (blockEntries == null) { - tmpEntries.add(new LayoutEntry(parsedEntry, prefs)); + tmpEntries.add(new LayoutEntry(parsedEntry, fileDirForDatabase, prefs)); } else { blockEntries.add(parsedEntry); } diff --git a/src/main/java/org/jabref/logic/layout/LayoutEntry.java b/src/main/java/org/jabref/logic/layout/LayoutEntry.java index 4b0434adb4b..2043953c218 100644 --- a/src/main/java/org/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/org/jabref/logic/layout/LayoutEntry.java @@ -7,6 +7,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import org.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; @@ -96,22 +97,21 @@ class LayoutEntry { private static final Logger LOGGER = LoggerFactory.getLogger(LayoutEntry.class); private List option; - // Formatter to be run after other formatters: private LayoutFormatter postFormatter; private String text; - private List layoutEntries; - private final int type; - private final List invalidFormatter = new ArrayList<>(); - private final LayoutFormatterPreferences prefs; + private final List fileDirForDatabase; + private final LayoutFormatterPreferences preferences; + + public LayoutEntry(StringInt si, List fileDirForDatabase, LayoutFormatterPreferences preferences) { + this.preferences = preferences; + this.fileDirForDatabase = Objects.requireNonNullElse(fileDirForDatabase, Collections.emptyList()); - public LayoutEntry(StringInt si, LayoutFormatterPreferences prefs) { - this.prefs = prefs; type = si.i; switch (type) { case LayoutHelper.IS_LAYOUT_TEXT: @@ -130,8 +130,10 @@ public LayoutEntry(StringInt si, LayoutFormatterPreferences prefs) { } } - public LayoutEntry(List parsedEntries, int layoutType, LayoutFormatterPreferences prefs) { - this.prefs = prefs; + public LayoutEntry(List parsedEntries, int layoutType, List fileDirForDatabase, LayoutFormatterPreferences preferences) { + this.preferences = preferences; + this.fileDirForDatabase = Objects.requireNonNullElse(fileDirForDatabase, Collections.emptyList()); + List tmpEntries = new ArrayList<>(); String blockStart = parsedEntries.get(0).s; String blockEnd = parsedEntries.get(parsedEntries.size() - 1).s; @@ -156,7 +158,7 @@ public LayoutEntry(List parsedEntries, int layoutType, LayoutFormatte blockEntries.add(parsedEntry); int groupType = parsedEntry.i == LayoutHelper.IS_GROUP_END ? LayoutHelper.IS_GROUP_START : LayoutHelper.IS_FIELD_START; - LayoutEntry le = new LayoutEntry(blockEntries, groupType, prefs); + LayoutEntry le = new LayoutEntry(blockEntries, groupType, fileDirForDatabase, preferences); tmpEntries.add(le); blockEntries = null; } else { @@ -172,7 +174,7 @@ public LayoutEntry(List parsedEntries, int layoutType, LayoutFormatte } if (blockEntries == null) { - tmpEntries.add(new LayoutEntry(parsedEntry, prefs)); + tmpEntries.add(new LayoutEntry(parsedEntry, fileDirForDatabase, preferences)); } else { blockEntries.add(parsedEntry); } @@ -443,7 +445,7 @@ private LayoutFormatter getLayoutFormatterByName(String name) { case "HTMLParagraphs" -> new HTMLParagraphs(); case "Iso690FormatDate" -> new Iso690FormatDate(); case "Iso690NamesAuthors" -> new Iso690NamesAuthors(); - case "JournalAbbreviator" -> new JournalAbbreviator(prefs.getJournalAbbreviationRepository()); + case "JournalAbbreviator" -> new JournalAbbreviator(preferences.getJournalAbbreviationRepository()); case "LastPage" -> new LastPage(); // For backward compatibility case "FormatChars", "LatexToUnicode" -> new LatexToUnicodeFormatter(); @@ -462,14 +464,14 @@ private LayoutFormatter getLayoutFormatterByName(String name) { case "ToUpperCase" -> new ToUpperCase(); case "XMLChars" -> new XMLChars(); case "Default" -> new Default(); - case "FileLink" -> new FileLink(prefs.getFileLinkPreferences()); + case "FileLink" -> new FileLink(fileDirForDatabase, preferences.getMainFileDirectory()); case "Number" -> new Number(); case "RisAuthors" -> new RisAuthors(); case "Authors" -> new Authors(); case "IfPlural" -> new IfPlural(); case "Replace" -> new Replace(); case "WrapContent" -> new WrapContent(); - case "WrapFileLinks" -> new WrapFileLinks(prefs.getFileLinkPreferences()); + case "WrapFileLinks" -> new WrapFileLinks(fileDirForDatabase, preferences.getMainFileDirectory()); case "Markdown" -> new MarkdownFormatter(); case "CSLType" -> new CSLType(); case "ShortMonth" -> new ShortMonthFormatter(); @@ -483,12 +485,12 @@ private LayoutFormatter getLayoutFormatterByName(String name) { private List getOptionalLayout(String formatterName) { List> formatterStrings = parseMethodsCalls(formatterName); List results = new ArrayList<>(formatterStrings.size()); - Map userNameFormatter = NameFormatter.getNameFormatters(prefs.getNameFormatterPreferences()); + Map userNameFormatter = NameFormatter.getNameFormatters(preferences.getNameFormatterPreferences()); for (List strings : formatterStrings) { String nameFormatterName = strings.get(0).trim(); // Check if this is a name formatter defined by this export filter: - Optional contents = prefs.getCustomExportNameFormatter(nameFormatterName); + Optional contents = preferences.getCustomExportNameFormatter(nameFormatterName); if (contents.isPresent()) { NameFormatter nf = new NameFormatter(); nf.setParameter(contents.get()); diff --git a/src/main/java/org/jabref/logic/layout/LayoutFormatterPreferences.java b/src/main/java/org/jabref/logic/layout/LayoutFormatterPreferences.java index 6952cc24b28..64c8e438117 100644 --- a/src/main/java/org/jabref/logic/layout/LayoutFormatterPreferences.java +++ b/src/main/java/org/jabref/logic/layout/LayoutFormatterPreferences.java @@ -4,22 +4,23 @@ import java.util.Map; import java.util.Optional; +import javafx.beans.property.StringProperty; + import org.jabref.logic.journals.JournalAbbreviationRepository; -import org.jabref.logic.layout.format.FileLinkPreferences; import org.jabref.logic.layout.format.NameFormatterPreferences; public class LayoutFormatterPreferences { private final NameFormatterPreferences nameFormatterPreferences; - private final FileLinkPreferences fileLinkPreferences; + private final StringProperty mainFileDirectoryProperty; private final Map customExportNameFormatters = new HashMap<>(); private final JournalAbbreviationRepository journalAbbreviationRepository; public LayoutFormatterPreferences(NameFormatterPreferences nameFormatterPreferences, - FileLinkPreferences fileLinkPreferences, + StringProperty mainFileDirectoryProperty, JournalAbbreviationRepository journalAbbreviationRepository) { this.nameFormatterPreferences = nameFormatterPreferences; - this.fileLinkPreferences = fileLinkPreferences; + this.mainFileDirectoryProperty = mainFileDirectoryProperty; this.journalAbbreviationRepository = journalAbbreviationRepository; } @@ -27,8 +28,8 @@ public NameFormatterPreferences getNameFormatterPreferences() { return nameFormatterPreferences; } - public FileLinkPreferences getFileLinkPreferences() { - return fileLinkPreferences; + public String getMainFileDirectory() { + return mainFileDirectoryProperty.get(); } public JournalAbbreviationRepository getJournalAbbreviationRepository() { diff --git a/src/main/java/org/jabref/logic/layout/LayoutHelper.java b/src/main/java/org/jabref/logic/layout/LayoutHelper.java index 1d522f67eca..69aafdd1dcf 100644 --- a/src/main/java/org/jabref/logic/layout/LayoutHelper.java +++ b/src/main/java/org/jabref/logic/layout/LayoutHelper.java @@ -3,7 +3,9 @@ import java.io.IOException; import java.io.PushbackReader; import java.io.Reader; +import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -35,12 +37,18 @@ public class LayoutHelper { private final PushbackReader in; private final List parsedEntries = new ArrayList<>(); - private final LayoutFormatterPreferences prefs; + private final List fileDirForDatabase; + private final LayoutFormatterPreferences preferences; private boolean endOfFile; - public LayoutHelper(Reader in, LayoutFormatterPreferences prefs) { + public LayoutHelper(Reader in, List fileDirForDatabase, LayoutFormatterPreferences preferences) { this.in = new PushbackReader(Objects.requireNonNull(in)); - this.prefs = Objects.requireNonNull(prefs); + this.preferences = Objects.requireNonNull(preferences); + this.fileDirForDatabase = fileDirForDatabase; + } + + public LayoutHelper(Reader in, LayoutFormatterPreferences preferences) { + this(in, Collections.emptyList(), preferences); } public Layout getLayoutFromText() throws IOException { @@ -54,7 +62,7 @@ public Layout getLayoutFromText() throws IOException { } } - return new Layout(parsedEntries, prefs); + return new Layout(parsedEntries, fileDirForDatabase, preferences); } public static String getCurrentGroup() { diff --git a/src/main/java/org/jabref/logic/layout/format/FileLink.java b/src/main/java/org/jabref/logic/layout/format/FileLink.java index 79a5b4b31fc..73bd58e7e76 100644 --- a/src/main/java/org/jabref/logic/layout/format/FileLink.java +++ b/src/main/java/org/jabref/logic/layout/format/FileLink.java @@ -14,11 +14,13 @@ */ public class FileLink implements ParamLayoutFormatter { - private final FileLinkPreferences prefs; + private final List fileDirectories; + private final String mainFileDirectory; private String fileType; - public FileLink(FileLinkPreferences fileLinkPreferences) { - this.prefs = fileLinkPreferences; + public FileLink(List fileDirectories, String mainFileDirectory) { + this.fileDirectories = fileDirectories; + this.mainFileDirectory = mainFileDirectory; } @Override @@ -50,14 +52,10 @@ public String format(String field) { } List dirs; - // We need to resolve the file directory from the database's metadata, - // but that is not available from a formatter. Therefore, as an - // ugly hack, the export routine has set a global variable before - // starting the export, which contains the database's file directory: - if (prefs.getFileDirForDatabase() == null) { - dirs = Collections.singletonList(Path.of(prefs.getMainFileDirectory())); + if (fileDirectories.isEmpty()) { + dirs = Collections.singletonList(Path.of(mainFileDirectory)); } else { - dirs = prefs.getFileDirForDatabase(); + dirs = fileDirectories; } return link.findIn(dirs) diff --git a/src/main/java/org/jabref/logic/layout/format/FileLinkPreferences.java b/src/main/java/org/jabref/logic/layout/format/FileLinkPreferences.java deleted file mode 100644 index 20b9dcd067e..00000000000 --- a/src/main/java/org/jabref/logic/layout/format/FileLinkPreferences.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.jabref.logic.layout.format; - -import java.nio.file.Path; -import java.util.List; - -public class FileLinkPreferences { - - private final String mainFileDirectory; - private final List fileDirForDatabase; - - public FileLinkPreferences(String mainFileDirectory, List fileDirForDatabase) { - this.mainFileDirectory = mainFileDirectory; - this.fileDirForDatabase = fileDirForDatabase; - } - - public String getMainFileDirectory() { - return mainFileDirectory; - } - - /** - * The following field is used as a global variable during the export of a database. - * By setting this field to the path of the database's default file directory, formatters - * that should resolve external file paths can access this field. This is an ugly hack - * to solve the problem of formatters not having access to any context except for the - * string to be formatted and possible formatter arguments. - * - * See also {@link org.jabref.preferences.JabRefPreferences#fileDirForDatabase} - */ - public List getFileDirForDatabase() { - return fileDirForDatabase; - } -} diff --git a/src/main/java/org/jabref/logic/layout/format/WrapFileLinks.java b/src/main/java/org/jabref/logic/layout/format/WrapFileLinks.java index f93c3e097b3..c8797036650 100644 --- a/src/main/java/org/jabref/logic/layout/format/WrapFileLinks.java +++ b/src/main/java/org/jabref/logic/layout/format/WrapFileLinks.java @@ -71,7 +71,7 @@ *

* would give the following output: * 1. An early "draft" (/home/john/draft.txt) - * + *

* Additional pairs of replacements can be added. */ public class WrapFileLinks extends AbstractParamLayoutFormatter { @@ -96,12 +96,14 @@ public class WrapFileLinks extends AbstractParamLayoutFormatter { } private final Map replacements = new HashMap<>(); - private final FileLinkPreferences prefs; + private final List fileDirectories; + private final String mainFileDirectory; private String fileType; private List format; - public WrapFileLinks(FileLinkPreferences fileLinkPreferences) { - this.prefs = fileLinkPreferences; + public WrapFileLinks(List fileDirectories, String mainFileDirectory) { + this.fileDirectories = fileDirectories; + this.mainFileDirectory = mainFileDirectory; } /** @@ -194,14 +196,10 @@ public String format(String field) { break; case FILE_PATH: List dirs; - // We need to resolve the file directory from the database's metadata, - // but that is not available from a formatter. Therefore, as an - // ugly hack, the export routine has set a global variable before - // starting the export, which contains the database's file directory: - if ((prefs.getFileDirForDatabase() == null) || prefs.getFileDirForDatabase().isEmpty()) { - dirs = Collections.singletonList(Path.of(prefs.getMainFileDirectory())); + if (fileDirectories.isEmpty()) { + dirs = Collections.singletonList(Path.of(mainFileDirectory)); } else { - dirs = prefs.getFileDirForDatabase(); + dirs = fileDirectories; } String pathString = flEntry.findIn(dirs) diff --git a/src/main/java/org/jabref/preferences/InternalPreferences.java b/src/main/java/org/jabref/preferences/InternalPreferences.java index 290dc628f29..be26c95a8b3 100644 --- a/src/main/java/org/jabref/preferences/InternalPreferences.java +++ b/src/main/java/org/jabref/preferences/InternalPreferences.java @@ -1,5 +1,7 @@ package org.jabref.preferences; +import java.nio.file.Path; + import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; @@ -10,10 +12,12 @@ public class InternalPreferences { private final ObjectProperty ignoredVersion; + private final ObjectProperty lastPreferencesExportPath; private final StringProperty user; - public InternalPreferences(Version ignoredVersion, String user) { + public InternalPreferences(Version ignoredVersion, Path exportPath, String user) { this.ignoredVersion = new SimpleObjectProperty<>(ignoredVersion); + this.lastPreferencesExportPath = new SimpleObjectProperty<>(exportPath); this.user = new SimpleStringProperty(user); } @@ -29,6 +33,18 @@ public void setIgnoredVersion(Version ignoredVersion) { this.ignoredVersion.set(ignoredVersion); } + public Path getLastPreferencesExportPath() { + return lastPreferencesExportPath.get(); + } + + public ObjectProperty lastPreferencesExportPathProperty() { + return lastPreferencesExportPath; + } + + public void setLastPreferencesExportPath(Path lastPreferencesExportPath) { + this.lastPreferencesExportPath.set(lastPreferencesExportPath); + } + public String getUser() { return user.get(); } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index ff0cb73e4dc..89f0c3ad273 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -81,7 +81,6 @@ import org.jabref.logic.l10n.Localization; import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.layout.TextBasedPreviewLayout; -import org.jabref.logic.layout.format.FileLinkPreferences; import org.jabref.logic.layout.format.NameFormatterPreferences; import org.jabref.logic.net.ProxyPreferences; import org.jabref.logic.net.ssl.SSLPreferences; @@ -403,13 +402,6 @@ public class JabRefPreferences implements PreferencesService { */ public final Map defaults = new HashMap<>(); - // The following field is used as a global variable during the export of a database. - // By setting this field to the path of the database's default file directory, formatters - // that should resolve external file paths can access this field. This is an ugly hack - // to solve the problem of formatters not having access to any context except for the - // string to be formatted and possible formatter arguments. - public List fileDirForDatabase; - private final Preferences prefs; /** @@ -1113,23 +1105,11 @@ public void importPreferences(Path file) throws JabRefException { } } - @Override - public FileLinkPreferences getFileLinkPreferences() { - return new FileLinkPreferences( - getFilePreferences().mainFileDirectoryProperty().get(), - fileDirForDatabase); - } - - @Override - public void storeFileDirForDatabase(List dirs) { - this.fileDirForDatabase = dirs; - } - @Override public LayoutFormatterPreferences getLayoutFormatterPreferences(JournalAbbreviationRepository repository) { return new LayoutFormatterPreferences( getNameFormatterPreferences(), - getFileLinkPreferences(), + getFilePreferences().mainFileDirectoryProperty(), repository); } @@ -1395,7 +1375,6 @@ public GroupsPreferences getGroupsPreferences() { EasyBind.listen(groupsPreferences.groupViewModeProperty(), (obs, oldValue, newValue) -> put(GROUP_INTERSECT_UNION_VIEW_MODE, newValue.name())); EasyBind.listen(groupsPreferences.autoAssignGroupProperty(), (obs, oldValue, newValue) -> putBoolean(AUTO_ASSIGN_GROUP, newValue)); EasyBind.listen(groupsPreferences.displayGroupCountProperty(), (obs, oldValue, newValue) -> putBoolean(DISPLAY_GROUP_COUNT, newValue)); - // KeywordSeparator is handled by JabRefPreferences::getInternalPreferences return groupsPreferences; } @@ -1407,7 +1386,7 @@ public GroupsPreferences getGroupsPreferences() { /** * Creates a list of defined tabs in the entry editor from cache * - * @return a list of defined tabs + * @return a map of defined tabs and associated fields */ private Map> getEntryEditorTabList() { if (entryEditorTabList == null) { @@ -1604,12 +1583,10 @@ private GlobalCitationKeyPattern getGlobalCitationKeyPattern() { Preferences preferences = PREFS_NODE.node(CITATION_KEY_PATTERNS_NODE); try { String[] keys = preferences.keys(); - if (keys.length > 0) { - for (String key : keys) { - citationKeyPattern.addCitationKeyPattern( - EntryTypeFactory.parse(key), - preferences.get(key, null)); - } + for (String key : keys) { + citationKeyPattern.addCitationKeyPattern( + EntryTypeFactory.parse(key), + preferences.get(key, null)); } } catch ( BackingStoreException ex) { @@ -2004,7 +1981,7 @@ private List storeColumnPreferences(ColumnPreferences colu } //************************************************************************************************************* - // InternalPreferences + // BibEntryPreferences //************************************************************************************************************* @Override @@ -2034,10 +2011,14 @@ public InternalPreferences getInternalPreferences() { internalPreferences = new InternalPreferences( Version.parse(get(VERSION_IGNORED_UPDATE)), + getPath(PREFS_EXPORT_PATH, JabRefDesktop.getNativeDesktop().getDefaultFileChooserDirectory()), getUser() ); - EasyBind.listen(internalPreferences.ignoredVersionProperty(), (obs, oldValue, newValue) -> put(VERSION_IGNORED_UPDATE, newValue.toString())); + EasyBind.listen(internalPreferences.ignoredVersionProperty(), + (obs, oldValue, newValue) -> put(VERSION_IGNORED_UPDATE, newValue.toString())); + EasyBind.listen(internalPreferences.lastPreferencesExportPathProperty(), + (obs, oldValue, newValue) -> put(PREFS_EXPORT_PATH, newValue.toString())); // user is a static value, should only be changed for debugging return internalPreferences; @@ -2723,16 +2704,6 @@ public SpecialFieldsPreferences getSpecialFieldsPreferences() { return specialFieldsPreferences; } - @Override - public String getLastPreferencesExportPath() { - return get(PREFS_EXPORT_PATH); - } - - @Override - public void storeLastPreferencesExportPath(Path exportFile) { - put(PREFS_EXPORT_PATH, exportFile.toString()); - } - @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 dfc07f50d54..d7e06f44c05 100644 --- a/src/main/java/org/jabref/preferences/PreferencesService.java +++ b/src/main/java/org/jabref/preferences/PreferencesService.java @@ -26,7 +26,6 @@ import org.jabref.logic.journals.JournalAbbreviationPreferences; import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.layout.LayoutFormatterPreferences; -import org.jabref.logic.layout.format.FileLinkPreferences; import org.jabref.logic.layout.format.NameFormatterPreferences; import org.jabref.logic.net.ProxyPreferences; import org.jabref.logic.net.ssl.SSLPreferences; @@ -194,10 +193,6 @@ public interface PreferencesService { AutoLinkPreferences getAutoLinkPreferences(); - FileLinkPreferences getFileLinkPreferences(); - - void storeFileDirForDatabase(List dirs); - //************************************************************************************************************* // Import/Export preferences //************************************************************************************************************* @@ -244,10 +239,6 @@ public interface PreferencesService { SearchPreferences getSearchPreferences(); - String getLastPreferencesExportPath(); - - void storeLastPreferencesExportPath(Path exportFile); - MrDlibPreferences getMrDlibPreferences(); ProtectedTermsPreferences getProtectedTermsPreferences(); diff --git a/src/test/java/org/jabref/cli/JabRefCLITest.java b/src/test/java/org/jabref/cli/JabRefCLITest.java index 981506fde93..7fb40505602 100644 --- a/src/test/java/org/jabref/cli/JabRefCLITest.java +++ b/src/test/java/org/jabref/cli/JabRefCLITest.java @@ -1,6 +1,7 @@ package org.jabref.cli; import java.util.Collections; +import java.util.List; import org.junit.jupiter.api.Test; @@ -129,4 +130,17 @@ void successfulParsingOfBibtexImportLong() throws Exception { assertEquals(bibtex, cli.getBibtexImport()); } + + @Test + void wrapStringList() { + List given = List.of("html", "simplehtml", "docbook5", "docbook4", "din1505", "bibordf", "tablerefs", "listrefs", + "tablerefsabsbib", "harvard", "iso690rtf", "iso690txt", "endnote", "oocsv", "ris", "misq", "yaml", "bibtexml", "oocalc", "ods", + "MSBib", "mods", "xmp", "pdf", "bib"); + String expected = """ + Available export formats: html, simplehtml, docbook5, docbook4, din1505, bibordf, tablerefs, + listrefs, tablerefsabsbib, harvard, iso690rtf, iso690txt, endnote, oocsv, ris, misq, yaml, bibtexml, + oocalc, ods, MSBib, mods, xmp, pdf, bib"""; + + assertEquals(expected, "Available export formats: " + JabRefCLI.wrapStringList(given, 26)); + } } diff --git a/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java b/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java index e1f400630b9..7ec45efaef7 100644 --- a/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java +++ b/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java @@ -16,15 +16,11 @@ import org.jabref.logic.exporter.Exporter; import org.jabref.logic.exporter.ExporterFactory; import org.jabref.logic.exporter.SavePreferences; -import org.jabref.logic.exporter.TemplateExporter; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.util.StandardFileType; import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; import org.jabref.model.metadata.MetaData; @@ -52,7 +48,7 @@ public class ExportToClipboardActionTest { private final DialogService dialogService = spy(DialogService.class); private final ClipBoardManager clipBoardManager = mock(ClipBoardManager.class); private final BibDatabaseContext databaseContext = mock(BibDatabaseContext.class); - private final PreferencesService preferences = spy(PreferencesService.class); + private final PreferencesService preferences = mock(PreferencesService.class); private final ImportExportPreferences importExportPrefs = mock(ImportExportPreferences.class); private final StateManager stateManager = mock(StateManager.class); @@ -73,13 +69,10 @@ public void setUp() { when(stateManager.getSelectedEntries()).thenReturn(selectedEntries); taskExecutor = new CurrentThreadTaskExecutor(); - List customFormats = new ArrayList<>(); - LayoutFormatterPreferences layoutPreferences = mock(LayoutFormatterPreferences.class, Answers.RETURNS_DEEP_STUBS); - SavePreferences savePreferences = mock(SavePreferences.class); - XmpPreferences xmpPreferences = mock(XmpPreferences.class); - BibEntryTypesManager entryTypesManager = mock(BibEntryTypesManager.class); - exporterFactory = ExporterFactory.create(customFormats, layoutPreferences, savePreferences, xmpPreferences, BibDatabaseMode.BIBTEX, entryTypesManager); - exportToClipboardAction = new ExportToClipboardAction(dialogService, exporterFactory, stateManager, clipBoardManager, taskExecutor, preferences); + when(preferences.getCustomExportFormats(any())).thenReturn(List.of()); + when(preferences.getSavePreferencesForExport()).thenReturn(mock(SavePreferences.class)); + when(preferences.getXmpPreferences()).thenReturn(mock(XmpPreferences.class)); + exportToClipboardAction = new ExportToClipboardAction(dialogService, stateManager, clipBoardManager, taskExecutor, preferences); } @Test @@ -110,8 +103,12 @@ public void export(BibDatabaseContext databaseContext, Path file, List when(databaseContext.getFileDirectories(preferences.getFilePreferences())).thenReturn(new ArrayList<>(List.of(Path.of("path")))); when(databaseContext.getMetaData()).thenReturn(new MetaData()); when(dialogService.showChoiceDialogAndWait( - eq(Localization.lang("Export")), eq(Localization.lang("Select export format")), - eq(Localization.lang("Export")), any(Exporter.class), anyCollection())).thenReturn(Optional.of(selectedExporter)); + eq(Localization.lang("Export")), + eq(Localization.lang("Select export format")), + eq(Localization.lang("Export")), + any(Exporter.class), + anyCollection()) + ).thenReturn(Optional.of(selectedExporter)); exportToClipboardAction.execute(); verify(dialogService, times(1)).showChoiceDialogAndWait( diff --git a/src/test/java/org/jabref/logic/layout/LayoutTest.java b/src/test/java/org/jabref/logic/layout/LayoutTest.java index b9700d9faf5..a41c65fe801 100644 --- a/src/test/java/org/jabref/logic/layout/LayoutTest.java +++ b/src/test/java/org/jabref/logic/layout/LayoutTest.java @@ -5,8 +5,8 @@ import java.io.StringReader; import java.nio.file.Path; import java.util.Collections; +import java.util.List; -import org.jabref.logic.layout.format.FileLinkPreferences; import org.jabref.logic.layout.format.NameFormatterPreferences; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; @@ -31,14 +31,18 @@ void setUp() { layoutFormatterPreferences = mock(LayoutFormatterPreferences.class, Answers.RETURNS_DEEP_STUBS); } - private String layout(String layout, BibEntry entry) throws IOException { + private String layout(String layout, List fileDirForDatabase, BibEntry entry) throws IOException { StringReader layoutStringReader = new StringReader(layout.replace("__NEWLINE__", "\n")); - return new LayoutHelper(layoutStringReader, layoutFormatterPreferences) + return new LayoutHelper(layoutStringReader, fileDirForDatabase, layoutFormatterPreferences) .getLayoutFromText() .doLayout(entry, null); } + private String layout(String layout, BibEntry entry) throws IOException { + return layout(layout, Collections.emptyList(), entry); + } + @Test void entryTypeForUnknown() throws IOException { BibEntry entry = new BibEntry(new UnknownEntryType("unknown")).withField(StandardField.AUTHOR, "test"); @@ -134,12 +138,13 @@ void beginConditionals() throws IOException { */ @Test void wrapFileLinksExpandFile() throws IOException { - when(layoutFormatterPreferences.getFileLinkPreferences()).thenReturn( - new FileLinkPreferences("", Collections.singletonList(Path.of("src/test/resources/pdfs/")))); BibEntry entry = new BibEntry(StandardEntryType.Article); entry.addFile(new LinkedFile("Test file", Path.of("encrypted.pdf"), "PDF")); - String layoutText = layout("\\begin{file}\\format[WrapFileLinks(\\i. \\d (\\p))]{\\file}\\end{file}", entry); + String layoutText = layout( + "\\begin{file}\\format[WrapFileLinks(\\i. \\d (\\p))]{\\file}\\end{file}", + Collections.singletonList(Path.of("src/test/resources/pdfs/")), + entry); assertEquals( "1. Test file (" + new File("src/test/resources/pdfs/encrypted.pdf").getCanonicalPath() + ")", diff --git a/src/test/java/org/jabref/logic/layout/format/FileLinkTest.java b/src/test/java/org/jabref/logic/layout/format/FileLinkTest.java index 7519473feb0..c7cd3c46302 100644 --- a/src/test/java/org/jabref/logic/layout/format/FileLinkTest.java +++ b/src/test/java/org/jabref/logic/layout/format/FileLinkTest.java @@ -1,5 +1,6 @@ package org.jabref.logic.layout.format; +import java.util.Collections; import java.util.stream.Stream; import org.jabref.logic.layout.ParamLayoutFormatter; @@ -10,17 +11,14 @@ import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; public class FileLinkTest { - private FileLinkPreferences prefs; private ParamLayoutFormatter fileLinkLayoutFormatter; @BeforeEach public void setUp() throws Exception { - prefs = mock(FileLinkPreferences.class); - fileLinkLayoutFormatter = new FileLink(prefs); + fileLinkLayoutFormatter = new FileLink(Collections.emptyList(), ""); } @ParameterizedTest diff --git a/src/test/java/org/jabref/logic/layout/format/WrapFileLinksTest.java b/src/test/java/org/jabref/logic/layout/format/WrapFileLinksTest.java index aad1356ab1d..faf60d71945 100644 --- a/src/test/java/org/jabref/logic/layout/format/WrapFileLinksTest.java +++ b/src/test/java/org/jabref/logic/layout/format/WrapFileLinksTest.java @@ -17,8 +17,7 @@ class WrapFileLinksTest { @BeforeEach void setUp() { - FileLinkPreferences preferences = new FileLinkPreferences("", Collections.emptyList()); - formatter = new WrapFileLinks(preferences); + formatter = new WrapFileLinks(Collections.emptyList(), ""); } @Test @@ -31,6 +30,7 @@ void testNull() { assertEquals("", formatter.format(null)); } + @Test void testNoFormatSetNonEmptyString() { assertThrows(NullPointerException.class, () -> formatter.format("test.pdf")); } @@ -97,9 +97,7 @@ void testEndingBracket() { @Test void testPath() throws IOException { - FileLinkPreferences preferences = new FileLinkPreferences("", - Collections.singletonList(Path.of("src/test/resources/pdfs/"))); - formatter = new WrapFileLinks(preferences); + formatter = new WrapFileLinks(Collections.singletonList(Path.of("src/test/resources/pdfs/")), ""); formatter.setArgument("\\p"); assertEquals(new File("src/test/resources/pdfs/encrypted.pdf").getCanonicalPath(), formatter.format("Preferences:encrypted.pdf:PDF")); @@ -107,9 +105,7 @@ void testPath() throws IOException { @Test void testPathFallBackToGeneratedDir() throws IOException { - FileLinkPreferences preferences = new FileLinkPreferences("src/test/resources/pdfs/", - Collections.emptyList()); - formatter = new WrapFileLinks(preferences); + formatter = new WrapFileLinks(Collections.emptyList(), "src/test/resources/pdfs/"); formatter.setArgument("\\p"); assertEquals(new File("src/test/resources/pdfs/encrypted.pdf").getCanonicalPath(), formatter.format("Preferences:encrypted.pdf:PDF")); @@ -117,9 +113,7 @@ void testPathFallBackToGeneratedDir() throws IOException { @Test void testPathReturnsRelativePathIfNotFound() { - FileLinkPreferences preferences = new FileLinkPreferences("", - Collections.singletonList(Path.of("src/test/resources/pdfs/"))); - formatter = new WrapFileLinks(preferences); + formatter = new WrapFileLinks(Collections.singletonList(Path.of("src/test/resources/pdfs/")), ""); formatter.setArgument("\\p"); assertEquals("test.pdf", formatter.format("Preferences:test.pdf:PDF")); }