Skip to content

Commit

Permalink
Refactor of DOI import failure dialog, import format reader and clipb…
Browse files Browse the repository at this point in the history
…oard manager (#8839)

Co-authored-by: Siedlerchr <[email protected]>
  • Loading branch information
zkl-ai and Siedlerchr authored Aug 6, 2022
1 parent b2125ad commit 16de272
Show file tree
Hide file tree
Showing 43 changed files with 373 additions and 196 deletions.
93 changes: 7 additions & 86 deletions src/main/java/org/jabref/gui/ClipBoardManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

Expand All @@ -22,19 +19,8 @@
import org.jabref.architecture.AllowedToUseAwt;
import org.jabref.logic.bibtex.BibEntryWriter;
import org.jabref.logic.bibtex.FieldWriter;
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImportException;
import org.jabref.logic.importer.ImportFormatReader;
import org.jabref.logic.importer.ImportFormatReader.UnknownFormatImport;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.fetcher.ArXiv;
import org.jabref.logic.importer.fetcher.DoiFetcher;
import org.jabref.logic.importer.fileformat.BibtexParser;
import org.jabref.model.database.BibDatabaseMode;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.identifier.ArXivIdentifier;
import org.jabref.model.entry.identifier.DOI;
import org.jabref.model.util.OptionalUtil;
import org.jabref.preferences.PreferencesService;

import org.slf4j.Logger;
Expand All @@ -49,18 +35,16 @@ public class ClipBoardManager {

private static Clipboard clipboard;
private static java.awt.datatransfer.Clipboard primary;
private static ImportFormatReader importFormatReader;

private final PreferencesService preferencesService;

public ClipBoardManager(PreferencesService preferencesService) {
this(Clipboard.getSystemClipboard(), Toolkit.getDefaultToolkit().getSystemSelection(), Globals.IMPORT_FORMAT_READER, preferencesService);
this(Clipboard.getSystemClipboard(), Toolkit.getDefaultToolkit().getSystemSelection(), preferencesService);
}

public ClipBoardManager(Clipboard clipboard, java.awt.datatransfer.Clipboard primary, ImportFormatReader importFormatReader, PreferencesService preferencesService) {
public ClipBoardManager(Clipboard clipboard, java.awt.datatransfer.Clipboard primary, PreferencesService preferencesService) {
ClipBoardManager.clipboard = clipboard;
ClipBoardManager.primary = primary;
ClipBoardManager.importFormatReader = importFormatReader;

this.preferencesService = preferencesService;
}

Expand Down Expand Up @@ -103,6 +87,10 @@ public static String getContents() {
return result;
}

public Optional<String> getBibTeXEntriesFromClipbaord() {
return Optional.ofNullable(clipboard.getContent(DragAndDropDataFormats.ENTRIES)).map(String.class::cast);
}

/**
* Get the String residing on the primary clipboard (if it exists).
*
Expand Down Expand Up @@ -167,71 +155,4 @@ public void setContent(List<BibEntry> entries) throws IOException {
clipboard.setContent(content);
setPrimaryClipboardContent(content);
}

public List<BibEntry> extractData() {
Object entries = clipboard.getContent(DragAndDropDataFormats.ENTRIES);

if (entries == null) {
return handleStringData(clipboard.getString());
}
return handleBibTeXData((String) entries);
}

private List<BibEntry> handleBibTeXData(String entries) {
BibtexParser parser = new BibtexParser(preferencesService.getImportFormatPreferences(), Globals.getFileUpdateMonitor());
try {
return parser.parseEntries(new ByteArrayInputStream(entries.getBytes(StandardCharsets.UTF_8)));
} catch (ParseException ex) {
LOGGER.error("Could not paste", ex);
return Collections.emptyList();
}
}

private List<BibEntry> handleStringData(String data) {
if ((data == null) || data.isEmpty()) {
return Collections.emptyList();
}

Optional<DOI> doi = DOI.parse(data);
if (doi.isPresent()) {
return fetchByDOI(doi.get());
}
Optional<ArXivIdentifier> arXiv = ArXivIdentifier.parse(data);
if (arXiv.isPresent()) {
return fetchByArXiv(arXiv.get());
}

return tryImportFormats(data);
}

private List<BibEntry> tryImportFormats(String data) {
try {
UnknownFormatImport unknownFormatImport = importFormatReader.importUnknownFormat(data);
return unknownFormatImport.parserResult.getDatabase().getEntries();
} catch (ImportException ignored) {
return Collections.emptyList();
}
}

private List<BibEntry> fetchByDOI(DOI doi) {
LOGGER.info("Found DOI in clipboard");
try {
Optional<BibEntry> entry = new DoiFetcher(preferencesService.getImportFormatPreferences()).performSearchById(doi.getDOI());
return OptionalUtil.toList(entry);
} catch (FetcherException ex) {
LOGGER.error("Error while fetching", ex);
return Collections.emptyList();
}
}

private List<BibEntry> fetchByArXiv(ArXivIdentifier arXivIdentifier) {
LOGGER.info("Found arxiv identifier in clipboard");
try {
Optional<BibEntry> entry = new ArXiv(preferencesService.getImportFormatPreferences()).performSearchById(arXivIdentifier.getNormalizedWithoutVersion());
return OptionalUtil.toList(entry);
} catch (FetcherException ex) {
LOGGER.error("Error while fetching", ex);
return Collections.emptyList();
}
}
}
3 changes: 3 additions & 0 deletions src/main/java/org/jabref/gui/DefaultInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.jabref.gui.keyboard.KeyBindingRepository;
import org.jabref.gui.theme.ThemeManager;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.importer.ImportFormatReader;
import org.jabref.logic.journals.JournalAbbreviationRepository;
import org.jabref.logic.protectedterms.ProtectedTermsLoader;
import org.jabref.model.entry.BibEntryTypesManager;
Expand Down Expand Up @@ -52,6 +53,8 @@ private static Object createDependency(Class<?> clazz) {
return Globals.undoManager;
} else if (clazz == BibEntryTypesManager.class) {
return Globals.entryTypesManager;
} else if (clazz == ImportFormatReader.class) {
return Globals.IMPORT_FORMAT_READER;
} else {
try {
return clazz.newInstance();
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/org/jabref/gui/EntryTypeView.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.jabref.gui.util.IconValidationDecorator;
import org.jabref.gui.util.ViewModelListCellFactory;
import org.jabref.logic.importer.IdBasedFetcher;
import org.jabref.logic.importer.ImportFormatReader;
import org.jabref.logic.importer.WebFetcher;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseMode;
Expand All @@ -48,6 +49,7 @@
public class EntryTypeView extends BaseDialog<EntryType> {

@Inject StateManager stateManager;
@Inject ImportFormatReader importFormatReader;

@FXML private ButtonType generateButton;
@FXML private TextField idTextField;
Expand Down Expand Up @@ -119,7 +121,7 @@ private void addEntriesToPane(FlowPane pane, Collection<? extends BibEntryType>
@FXML
public void initialize() {
visualizer.setDecoration(new IconValidationDecorator());
viewModel = new EntryTypeViewModel(preferencesService, libraryTab, dialogService, stateManager);
viewModel = new EntryTypeViewModel(preferencesService, libraryTab, dialogService, stateManager, importFormatReader);

idBasedFetchers.itemsProperty().bind(viewModel.fetcherItemsProperty());
idTextField.textProperty().bindBidirectional(viewModel.idTextProperty());
Expand Down
25 changes: 18 additions & 7 deletions src/main/java/org/jabref/gui/EntryTypeViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
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;
import org.jabref.logic.importer.FetcherServerException;
import org.jabref.logic.importer.IdBasedFetcher;
import org.jabref.logic.importer.ImportFormatReader;
import org.jabref.logic.importer.WebFetchers;
import org.jabref.logic.importer.fetcher.DoiFetcher;
import org.jabref.logic.l10n.Localization;
Expand Down Expand Up @@ -50,15 +53,19 @@ public class EntryTypeViewModel {
private final DialogService dialogService;
private final Validator idFieldValidator;
private final StateManager stateManager;
private final ImportFormatReader importFormatReader;

public EntryTypeViewModel(PreferencesService preferences,
LibraryTab libraryTab,
DialogService dialogService,
StateManager stateManager) {
StateManager stateManager,
ImportFormatReader importFormatReader) {
this.libraryTab = libraryTab;
this.preferencesService = preferences;
this.dialogService = dialogService;
this.stateManager = stateManager;
this.importFormatReader = importFormatReader;

fetchers.addAll(WebFetchers.getIdBasedFetchers(
preferences.getImportFormatPreferences(),
preferences.getImporterPreferences()));
Expand Down Expand Up @@ -140,15 +147,18 @@ public void runFetcherWorker() {
String fetcherExceptionMessage = exception.getMessage();
String fetcher = selectedItemProperty().getValue().getName();
String searchId = idText.getValue();
if (exception instanceof FetcherException) {
dialogService.showErrorDialogAndWait(Localization.lang("Error"), Localization.lang("Error while fetching from %0", fetcher + "." + "\n" + fetcherExceptionMessage));

if (exception instanceof FetcherClientException) {
dialogService.showInformationDialogAndWait(Localization.lang("Failed to import by ID"), Localization.lang("Bibliographic data not found. Cause is likely the client side. Please check connection and identifier for correctness.") + "\n" + fetcherExceptionMessage);
} else if (exception instanceof FetcherServerException) {
dialogService.showInformationDialogAndWait(Localization.lang("Failed to import by ID"), Localization.lang("Bibliographic data not found. Cause is likely the server side. Please try agan later.") + "\n" + fetcherExceptionMessage);
} else {
dialogService.showErrorDialogAndWait(Localization.lang("No files found.", Localization.lang("Fetcher '%0' did not find an entry for id '%1'.", fetcher, searchId) + "\n" + fetcherExceptionMessage));
dialogService.showInformationDialogAndWait(Localization.lang("Failed to import by ID"), Localization.lang("Error message %0", fetcherExceptionMessage));
}

LOGGER.error(String.format("Exception during fetching when using fetcher '%s' with entry id '%s'.", searchId, fetcher), exception);

searchingProperty.set(false);

fetcherWorker = new FetcherWorker();
});

Expand All @@ -164,7 +174,8 @@ public void runFetcherWorker() {
Globals.getFileUpdateMonitor(),
libraryTab.getUndoManager(),
stateManager,
dialogService);
dialogService,
importFormatReader);
handler.importEntryWithDuplicateCheck(libraryTab.getBibDatabaseContext(), entry);

searchSuccesfulProperty.set(true);
Expand All @@ -177,7 +188,7 @@ public void runFetcherWorker() {
String searchId = idText.getValue();

// When DOI ID is not found, allow the user to either return to the dialog or add entry manually
boolean addEntryFlag = dialogService.showConfirmationDialogAndWait(Localization.lang("DOI not found"),
boolean addEntryFlag = dialogService.showConfirmationDialogAndWait(Localization.lang("Identifier not found"),
Localization.lang("Fetcher '%0' did not find an entry for id '%1'.", fetcher, searchId),
Localization.lang("Add entry manually"),
Localization.lang("Return to dialog"));
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
import org.jabref.logic.help.HelpFile;
import org.jabref.logic.importer.IdFetcher;
import org.jabref.logic.importer.ImportCleanup;
import org.jabref.logic.importer.ImportFormatReader;
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.importer.WebFetchers;
import org.jabref.logic.l10n.Localization;
Expand Down Expand Up @@ -183,6 +184,7 @@ public class JabRefFrame extends BorderPane {
private Subscription dividerSubscription;

private final TaskExecutor taskExecutor;
private final ImportFormatReader importFormatReader;

public JabRefFrame(Stage mainStage) {
this.mainStage = mainStage;
Expand All @@ -194,6 +196,7 @@ public JabRefFrame(Stage mainStage) {
this.globalSearchBar = new GlobalSearchBar(this, stateManager, prefs, undoManager);
this.fileHistory = new FileHistoryMenu(prefs, dialogService, getOpenDatabaseAction());
this.taskExecutor = Globals.TASK_EXECUTOR;
this.importFormatReader = Globals.IMPORT_FORMAT_READER;
this.setOnKeyTyped(key -> {
if (this.fileHistory.isShowing()) {
if (this.fileHistory.openFileByKey(key)) {
Expand Down Expand Up @@ -1140,7 +1143,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());
LibraryTab libraryTab = new LibraryTab(this, prefs, stateManager, themeManager, databaseContext, ExternalFileTypes.getInstance(), importFormatReader);
addTab(libraryTab, raisePanel);
return libraryTab;
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/gui/JabRefMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private static void applyPreferences(PreferencesService preferences) {

// Build list of Import and Export formats
Globals.IMPORT_FORMAT_READER.resetImportFormats(preferences.getImporterPreferences(),
preferences.getGeneralPreferences(), preferences.getImportFormatPreferences(),
preferences.getImportFormatPreferences(),
preferences.getXmpPreferences(), Globals.getFileUpdateMonitor());
Globals.entryTypesManager.addCustomOrModifiedTypes(preferences.getBibEntryTypes(BibDatabaseMode.BIBTEX),
preferences.getBibEntryTypes(BibDatabaseMode.BIBLATEX));
Expand Down
16 changes: 11 additions & 5 deletions src/main/java/org/jabref/gui/LibraryTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.jabref.logic.autosaveandbackup.AutosaveManager;
import org.jabref.logic.autosaveandbackup.BackupManager;
import org.jabref.logic.citationstyle.CitationStyleCache;
import org.jabref.logic.importer.ImportFormatReader;
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.importer.util.FileFieldParser;
import org.jabref.logic.l10n.Localization;
Expand Down Expand Up @@ -114,13 +115,15 @@ public class LibraryTab extends Tab {
private BackgroundTask<ParserResult> dataLoadingTask = BackgroundTask.wrap(() -> null);

private final IndexingTaskManager indexingTaskManager = new IndexingTaskManager(Globals.TASK_EXECUTOR);
private final ImportFormatReader importFormatReader;

public LibraryTab(JabRefFrame frame,
PreferencesService preferencesService,
StateManager stateManager,
ThemeManager themeManager,
BibDatabaseContext bibDatabaseContext,
ExternalFileTypes externalFileTypes) {
ExternalFileTypes externalFileTypes,
ImportFormatReader importFormatReader) {
this.frame = Objects.requireNonNull(frame);
this.bibDatabaseContext = Objects.requireNonNull(bibDatabaseContext);
this.externalFileTypes = Objects.requireNonNull(externalFileTypes);
Expand All @@ -129,6 +132,7 @@ public LibraryTab(JabRefFrame frame,
this.preferencesService = Objects.requireNonNull(preferencesService);
this.stateManager = Objects.requireNonNull(stateManager);
this.themeManager = Objects.requireNonNull(themeManager);
this.importFormatReader = importFormatReader;

bibDatabaseContext.getDatabase().registerListener(this);
bibDatabaseContext.getMetaData().registerListener(this);
Expand Down Expand Up @@ -485,7 +489,9 @@ private void createMainTable() {
dialogService,
stateManager,
externalFileTypes,
Globals.getKeyPrefs());
Globals.getKeyPrefs(),
Globals.getClipboardManager(),
Globals.IMPORT_FORMAT_READER);

// Add the listener that binds selection to state manager (TODO: should be replaced by proper JavaFX binding as soon as table is implemented in JavaFX)
mainTable.addSelectionListener(listEvent -> stateManager.setSelectedEntries(mainTable.getSelectedEntries()));
Expand Down Expand Up @@ -798,11 +804,11 @@ public void resetChangedProperties() {
}

public static class Factory {
public LibraryTab createLibraryTab(JabRefFrame frame, PreferencesService preferencesService, StateManager stateManager, ThemeManager themeManager, Path file, BackgroundTask<ParserResult> dataLoadingTask) {
public LibraryTab createLibraryTab(JabRefFrame frame, PreferencesService preferencesService, StateManager stateManager, ThemeManager themeManager, Path file, BackgroundTask<ParserResult> dataLoadingTask, ImportFormatReader importFormatReader) {
BibDatabaseContext context = new BibDatabaseContext();
context.setDatabasePath(file);

LibraryTab newTab = new LibraryTab(frame, preferencesService, stateManager, themeManager, context, ExternalFileTypes.getInstance());
LibraryTab newTab = new LibraryTab(frame, preferencesService, stateManager, themeManager, context, ExternalFileTypes.getInstance(), importFormatReader);
newTab.setDataLoadingTask(dataLoadingTask);

dataLoadingTask.onRunning(newTab::onDatabaseLoadingStarted)
Expand Down Expand Up @@ -938,7 +944,7 @@ public void notify(Node graphic, String text, List<Action> actions, Duration dur
this.setText(text);
this.getActions().setAll(actions);
this.show();
if (duration != null && !duration.equals(Duration.ZERO)) {
if ((duration != null) && !duration.equals(Duration.ZERO)) {
PauseTransition delay = new PauseTransition(duration);
delay.setOnFinished(e -> this.hide());
delay.play();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImportFormatReader;
import org.jabref.logic.importer.fetcher.GrobidCitationFetcher;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;
Expand All @@ -43,7 +44,8 @@ public BibtexExtractorViewModel(BibDatabaseContext bibdatabaseContext,
FileUpdateMonitor fileUpdateMonitor,
TaskExecutor taskExecutor,
UndoManager undoManager,
StateManager stateManager) {
StateManager stateManager,
ImportFormatReader importFormatReader) {

this.dialogService = dialogService;
this.preferencesService = preferencesService;
Expand All @@ -55,7 +57,8 @@ public BibtexExtractorViewModel(BibDatabaseContext bibdatabaseContext,
fileUpdateMonitor,
undoManager,
stateManager,
dialogService);
dialogService,
importFormatReader);
}

public StringProperty inputTextProperty() {
Expand Down
Loading

0 comments on commit 16de272

Please sign in to comment.