Skip to content

Commit

Permalink
Add merge dialog to import
Browse files Browse the repository at this point in the history
  • Loading branch information
InAnYan committed Dec 23, 2024
1 parent 783b2a5 commit 2b85c4f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 40 deletions.
27 changes: 20 additions & 7 deletions src/main/java/org/jabref/gui/externalfiles/ImportHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.jabref.gui.duplicationFinder.DuplicateResolverDialog;
import org.jabref.gui.fieldeditors.LinkedFileViewModel;
import org.jabref.gui.libraryproperties.constants.ConstantsItemModel;
import org.jabref.gui.mergeentries.MultiMergeEntriesView;
import org.jabref.gui.preferences.GuiPreferences;
import org.jabref.gui.undo.UndoableInsertEntries;
import org.jabref.gui.util.DragDrop;
Expand Down Expand Up @@ -100,6 +101,7 @@ public ExternalFilesEntryLinker getFileLinker() {
}

public BackgroundTask<List<ImportFilesResultItemViewModel>> importFilesInBackground(final List<Path> files, final BibDatabaseContext bibDatabaseContext, final FilePreferences filePreferences, TransferMode transferMode) {
// TODO: Make a class out of this :)
return new BackgroundTask<>() {
private int counter;
private final List<ImportFilesResultItemViewModel> results = new ArrayList<>();
Expand Down Expand Up @@ -128,18 +130,29 @@ public List<ImportFilesResultItemViewModel> call() {

try {
if (FileUtil.isPDFFile(file)) {
ParserResult pdfImporterResult = contentImporter.importPDFContent(file, bibDatabaseContext, filePreferences);
List<BibEntry> pdfEntriesInFile = pdfImporterResult.getDatabase().getEntries();

if (pdfImporterResult.hasWarnings()) {
addResultToList(file, false, Localization.lang("Error reading PDF content: %0", pdfImporterResult.getErrorMessage()));
List<BibEntry> pdfEntriesInFile;

// See {@link PdfMergeDialog#make} for reason why it is useful to call a merge dialog with
// various {@link PdfBibExtractor}s.
if (files.size() == 1) {
pdfEntriesInFile = new ArrayList<>();
UiTaskExecutor.runAndWaitInJavaFXThread(() -> {
MultiMergeEntriesView dialog = PdfMergeDialog.make(new BibEntry(), file, preferences, taskExecutor);
dialogService.showCustomDialogAndWait(dialog).ifPresent(pdfEntriesInFile::add);
});
} else {
ParserResult pdfImporterResult = contentImporter.importPDFContent(file, bibDatabaseContext, filePreferences);
pdfEntriesInFile = pdfImporterResult.getDatabase().getEntries();
if (pdfImporterResult.hasWarnings()) {
addResultToList(file, false, Localization.lang("Error reading PDF content: %0", pdfImporterResult.getErrorMessage()));
}
}

if (pdfEntriesInFile.isEmpty()) {
entriesToAdd.add(createEmptyEntryWithLink(file));
addResultToList(file, false, Localization.lang("No BibTeX was found. An empty entry was created with file link."));
} else {
pdfEntriesInFile.forEach(entry -> {
for (BibEntry entry : pdfEntriesInFile) {
if (entry.getFiles().size() > 1) {
LOGGER.warn("Entry has more than one file attached. This is not supported.");
LOGGER.warn("Entry's files: {}", entry.getFiles());
Expand All @@ -150,7 +163,7 @@ public List<ImportFilesResultItemViewModel> call() {
DragDrop.handleDropOfFiles(files, transferMode, fileLinker, entry);
entriesToAdd.addAll(pdfEntriesInFile);
addResultToList(file, true, Localization.lang("File was successfully imported as a new entry"));
});
}
}
} else if (FileUtil.isBibFile(file)) {
var bibtexParserResult = contentImporter.importFromBibFile(file, fileUpdateMonitor);
Expand Down
61 changes: 61 additions & 0 deletions src/main/java/org/jabref/gui/externalfiles/PdfMergeDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.jabref.gui.externalfiles;

import java.io.IOException;
import java.nio.file.Path;
import java.util.function.Supplier;

import org.jabref.gui.mergeentries.MultiMergeEntriesView;
import org.jabref.gui.preferences.GuiPreferences;
import org.jabref.logic.importer.Importer;
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.importer.fileformat.pdf.PdfEmbeddedBibExtractor;
import org.jabref.logic.importer.fileformat.pdf.PdfFirstPageBibExtractor;
import org.jabref.logic.importer.fileformat.pdf.PdfGrobidBibExtractor;
import org.jabref.logic.importer.fileformat.pdf.PdfVerbatimBibExtractor;
import org.jabref.logic.importer.fileformat.pdf.PdfXmpBibExtractor;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.TaskExecutor;
import org.jabref.model.entry.BibEntry;

public class PdfMergeDialog {
/**
* Constructs a merge dialog for a PDF file. This dialog merges results from various {@link org.jabref.logic.importer.fileformat.pdf.PdfBibExtractor}s.
* <p>
* {@link org.jabref.logic.importer.fileformat.pdf.PdfBibExtractor}s try to extract a {@link BibEntry} out of a PDF file,
* but it does not perform this 100% perfectly, it is only a set of heuristics that in some cases might work, in others not.
* Thus, JabRef provides this merge dialog that collects the results of all {@link org.jabref.logic.importer.fileformat.pdf.PdfBibExtractor}s
* and gives user a choice between field values.
*/
public static MultiMergeEntriesView make(BibEntry entry, Path filePath, GuiPreferences preferences, TaskExecutor taskExecutor) {
MultiMergeEntriesView dialog = new MultiMergeEntriesView(preferences, taskExecutor);

dialog.setTitle(Localization.lang("Merge PDF metadata"));

dialog.addSource(Localization.lang("Entry"), entry);
dialog.addSource(Localization.lang("Verbatim"), wrapImporterToSupplier(new PdfVerbatimBibExtractor(preferences.getImportFormatPreferences()), filePath));
dialog.addSource(Localization.lang("Embedded"), wrapImporterToSupplier(new PdfEmbeddedBibExtractor(preferences.getImportFormatPreferences()), filePath));

if (preferences.getGrobidPreferences().isGrobidEnabled()) {
dialog.addSource("Grobid", wrapImporterToSupplier(new PdfGrobidBibExtractor(preferences.getImportFormatPreferences()), filePath));
}

dialog.addSource(Localization.lang("XMP metadata"), wrapImporterToSupplier(new PdfXmpBibExtractor(preferences.getXmpPreferences()), filePath));
dialog.addSource(Localization.lang("Content"), wrapImporterToSupplier(new PdfFirstPageBibExtractor(), filePath));

return dialog;
}

private static Supplier<BibEntry> wrapImporterToSupplier(Importer importer, Path filePath) {
return () -> {
try {
ParserResult parserResult = importer.importDatabase(filePath);
if (parserResult.isInvalid() || parserResult.isEmpty() || !parserResult.getDatabase().hasEntries()) {
return null;
}
return parserResult.getDatabase().getEntries().getFirst();
} catch (IOException e) {
return null;
}
};
}
}
35 changes: 2 additions & 33 deletions src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import java.util.List;
import java.util.Optional;
import java.util.function.BiPredicate;
import java.util.function.Supplier;

import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
Expand All @@ -23,6 +22,7 @@
import org.jabref.gui.AbstractViewModel;
import org.jabref.gui.DialogService;
import org.jabref.gui.desktop.os.NativeDesktop;
import org.jabref.gui.externalfiles.PdfMergeDialog;
import org.jabref.gui.externalfiletype.ExternalFileType;
import org.jabref.gui.externalfiletype.ExternalFileTypes;
import org.jabref.gui.icon.IconTheme;
Expand All @@ -35,14 +35,6 @@
import org.jabref.gui.util.ControlHelper;
import org.jabref.logic.FilePreferences;
import org.jabref.logic.externalfiles.LinkedFileHandler;
import org.jabref.logic.importer.Importer;
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.importer.fileformat.PdfImporter;
import org.jabref.logic.importer.fileformat.pdf.PdfEmbeddedBibExtractor;
import org.jabref.logic.importer.fileformat.pdf.PdfFirstPageBibExtractor;
import org.jabref.logic.importer.fileformat.pdf.PdfGrobidBibExtractor;
import org.jabref.logic.importer.fileformat.pdf.PdfVerbatimBibExtractor;
import org.jabref.logic.importer.fileformat.pdf.PdfXmpBibExtractor;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.TaskExecutor;
import org.jabref.logic.util.io.FileUtil;
Expand Down Expand Up @@ -458,34 +450,11 @@ public ValidationStatus fileExistsValidationStatus() {

public void parsePdfMetadataAndShowMergeDialog() {
linkedFile.findIn(databaseContext, preferences.getFilePreferences()).ifPresent(filePath -> {
MultiMergeEntriesView dialog = new MultiMergeEntriesView(preferences, taskExecutor);
dialog.setTitle(Localization.lang("Merge PDF metadata"));
dialog.addSource(Localization.lang("Entry"), entry);
dialog.addSource(Localization.lang("Verbatim"), wrapImporterToSupplier(new PdfVerbatimBibExtractor(preferences.getImportFormatPreferences()), filePath));
dialog.addSource(Localization.lang("Embedded"), wrapImporterToSupplier(new PdfEmbeddedBibExtractor(preferences.getImportFormatPreferences()), filePath));
if (preferences.getGrobidPreferences().isGrobidEnabled()) {
dialog.addSource("Grobid", wrapImporterToSupplier(new PdfGrobidBibExtractor(preferences.getImportFormatPreferences()), filePath));
}
dialog.addSource(Localization.lang("XMP metadata"), wrapImporterToSupplier(new PdfXmpBibExtractor(preferences.getXmpPreferences()), filePath));
dialog.addSource(Localization.lang("Content"), wrapImporterToSupplier(new PdfFirstPageBibExtractor(), filePath));
MultiMergeEntriesView dialog = PdfMergeDialog.make(entry, filePath, preferences, taskExecutor);
dialogService.showCustomDialogAndWait(dialog).ifPresent(newEntry -> {
databaseContext.getDatabase().removeEntry(entry);
databaseContext.getDatabase().insertEntry(newEntry);
});
});
}

private Supplier<BibEntry> wrapImporterToSupplier(Importer importer, Path filePath) {
return () -> {
try {
ParserResult parserResult = importer.importDatabase(filePath);
if (parserResult.isInvalid() || parserResult.isEmpty() || !parserResult.getDatabase().hasEntries()) {
return null;
}
return parserResult.getDatabase().getEntries().getFirst();
} catch (IOException e) {
return null;
}
};
}
}

0 comments on commit 2b85c4f

Please sign in to comment.