package org.jabref.gui.externalfiles;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.JOptionPane;
import org.jabref.Globals;
import org.jabref.gui.BasePanel;
import org.jabref.gui.filelist.FileListTableModel;
import org.jabref.gui.undo.UndoableFieldChange;
import org.jabref.gui.worker.AbstractWorker;
import org.jabref.logic.importer.FulltextFetchers;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.FieldName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Try to download fulltext PDF for selected entry(ies) by following URL or DOI link.
*/
public class FindFullTextAction extends AbstractWorker {
private static final Log LOGGER = LogFactory.getLog(FindFullTextAction.class);
private static final int warningLimit = 5; // The minimum number of selected entries to ask the user for confirmation
private final BasePanel basePanel;
private final Map<Optional<URL>, BibEntry> downloads = new ConcurrentHashMap<>();
public FindFullTextAction(BasePanel basePanel) {
this.basePanel = basePanel;
}
@Override
public void init() throws Exception {
if (!basePanel.getSelectedEntries().isEmpty()) {
basePanel.output(Localization.lang("Looking for full text document..."));
} else {
LOGGER.debug("No entry selected for fulltext download.");
}
}
@Override
public void run() {
if (basePanel.getSelectedEntries().size() >= warningLimit) {
String[] options = new String[] {Localization.lang("Look up full text documents"),
Localization.lang("Cancel")};
int answer = JOptionPane.showOptionDialog(basePanel.frame(),
Localization.lang(
"You are about to look up full text documents for %0 entries.",
String.valueOf(basePanel.getSelectedEntries().size())) + "\n"
+ Localization.lang("JabRef will send at least one request per entry to a publisher.")
+ "\n"
+ Localization.lang("Do you still want to continue?"),
Localization.lang("Look up full text documents"), JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE, null, options, options[0]);
if (answer != JOptionPane.OK_OPTION) {
basePanel.output(Localization.lang("Operation canceled."));
return;
}
}
for (BibEntry entry : basePanel.getSelectedEntries()) {
FulltextFetchers fft = new FulltextFetchers(Globals.prefs.getImportFormatPreferences());
downloads.put(fft.findFullTextPDF(entry), entry);
}
}
@Override
public void update() {
List<Optional<URL>> remove = new ArrayList<>();
for (Entry<Optional<URL>, BibEntry> download : downloads.entrySet()) {
BibEntry entry = download.getValue();
Optional<URL> result = download.getKey();
if (result.isPresent()) {
List<String> dirs = basePanel.getBibDatabaseContext()
.getFileDirectories(Globals.prefs.getFileDirectoryPreferences());
if (dirs.isEmpty()) {
JOptionPane.showMessageDialog(basePanel.frame(),
Localization.lang("Main file directory not set!") + " " + Localization.lang("Preferences")
+ " -> " + Localization.lang("File"),
Localization.lang("Directory not found"), JOptionPane.ERROR_MESSAGE);
return;
}
DownloadExternalFile def = new DownloadExternalFile(basePanel.frame(),
basePanel.getBibDatabaseContext(), entry);
try {
def.download(result.get(), file -> {
FileListTableModel fileLinkModel = new FileListTableModel();
entry.getField(FieldName.FILE).ifPresent(fileLinkModel::setContent);
// add full text file link at first position
fileLinkModel.addEntry(0, file);
String newValue = fileLinkModel.getStringRepresentation();
UndoableFieldChange edit = new UndoableFieldChange(entry, FieldName.FILE,
entry.getField(FieldName.FILE).orElse(null), newValue);
entry.setField(FieldName.FILE, newValue);
basePanel.getUndoManager().addEdit(edit);
basePanel.markBaseChanged();
});
} catch (IOException e) {
LOGGER.warn("Problem downloading file", e);
}
basePanel.output(Localization.lang("Finished downloading full text document for entry %0.",
entry.getCiteKeyOptional().orElse(Localization.lang("undefined"))));
} else {
String title = Localization.lang("Full text document download failed");
String message = Localization.lang("Full text document download failed for entry %0.",
entry.getCiteKeyOptional().orElse(Localization.lang("undefined")));
basePanel.output(message);
JOptionPane.showMessageDialog(basePanel.frame(), message, title, JOptionPane.ERROR_MESSAGE);
}
remove.add(result);
}
for (Optional<URL> result : remove) {
downloads.remove(result);
}
}
}