package org.jabref.gui.entryeditor; import java.io.IOException; import java.net.URL; import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; import javax.swing.JEditorPane; import javax.swing.SwingWorker; import javax.swing.event.HyperlinkEvent; import org.jabref.Globals; import org.jabref.gui.IconTheme; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.logic.importer.fetcher.MrDLibFetcher; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; import org.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * This Component is displaying the recommendations received from Mr. DLib. * */ public class EntryEditorTabRelatedArticles extends JEditorPane { private static final Log LOGGER = LogFactory.getLog(EntryEditorTabRelatedArticles.class); //The entry the user selects in the table private final BibEntry selectedEntry; private List<BibEntry> relatedArticles; private Boolean onFocus = true; /** * Takes the selected entry, runs a request to Mr. DLib and returns the recommendations as a JEditorPane * @param selectedEntry The entry selected by the user */ public EntryEditorTabRelatedArticles(BibEntry selectedEntry) { this.selectedEntry = selectedEntry; this.setContentType("text/html"); this.setEditable(false); registerHyperlinkListener(); setDefaultContent(); } /** * Access related acticles delivered by Mr. DLib. * @return the list of BibEntries, representing the related articles deliverd by MR. DLib */ public List<BibEntry> getRelatedArticles() { return relatedArticles; } /** * Takes a List of HTML snippets stored in the field "html_representation" of a list of bibentries and sets it in the JEditorPane * * @param list of bib entries having a field html_representation */ public void setHtmlText(List<BibEntry> list) { StringBuilder htmlContent = new StringBuilder(); URL url = IconTheme.getIconUrl("mdlListIcon"); htmlContent .append("<html><head><title></title></head><body bgcolor='#ffffff'>"); htmlContent.append("<ul style='list-style-image:("); htmlContent.append(url); htmlContent.append(")'>"); list.stream() .map(bibEntry -> bibEntry.getField("html_representation")) .filter(Optional::isPresent) .map(o -> "<li style='margin: 5px'>" + o.get() + "</li>") .forEach(html -> htmlContent.append(html)); htmlContent.append("</ul>"); htmlContent.append("<br><div style='margin-left: 5px'>"); htmlContent.append( "<a href='http://mr-dlib.org/information-for-users/information-about-mr-dlib-for-jabref-users/#'>"); htmlContent.append(Localization.lang("What_is_Mr._DLib?")); htmlContent.append("</a></div>"); htmlContent.append("</body></html>"); this.setText(htmlContent.toString()); } /** * While the fetcher gets the Recommendations from MR. DLib this content indicates * that the search is in Progress */ private void setDefaultContent() { StringBuilder htmlContent = new StringBuilder(); URL url = IconTheme.getIconUrl("mdlloading"); htmlContent .append("<html><head><title></title></head><body bgcolor='#ffffff'><div align='center' style='font-size:20px'>"); htmlContent.append(Localization.lang("Loading_Recommendations_for")); htmlContent.append(": "); htmlContent.append("<b>"); htmlContent.append(selectedEntry.getLatexFreeField(FieldName.TITLE).orElseGet(() -> "")); htmlContent.append("<div>"); htmlContent.append( "<a href='http://mr-dlib.org/information-for-users/information-about-mr-dlib-for-jabref-users/#'>"); htmlContent.append(Localization.lang("What_is_Mr._DLib?")); htmlContent.append("</a></div>"); htmlContent.append("</b><br><img width=\"100\" height=\"100\" src=\"" + url + "\"></img></div>"); htmlContent.append("</body></html>"); this.setText(htmlContent.toString()); } /** * Makes the Hyperlinks clickable. Opens the link destination in a Browsertab */ private void registerHyperlinkListener() { this.addHyperlinkListener(e -> { try { if ((e.getURL() != null) && (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)) { JabRefDesktop.openBrowser(e.getURL().toString()); } } catch (IOException e1) { LOGGER.error(e1.getMessage(), e1); } }); } public void focus() { if (onFocus) { requestRecommendations(); onFocus = false; } } /** * Starts a Fetcher getting the recommendations form Mr. DLib */ public void requestRecommendations() { //The Fetcher delivers the recommendations MrDLibFetcherWorker mdlFetcher; try { mdlFetcher = new MrDLibFetcherWorker(selectedEntry); mdlFetcher.addPropertyChangeListener(evt -> { if (evt.getNewValue().equals(SwingWorker.StateValue.DONE)) { try { relatedArticles = mdlFetcher.get(); setHtmlText(relatedArticles); } catch (InterruptedException | ExecutionException e) { LOGGER.error(e.getMessage(), e); } } }); mdlFetcher.execute(); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } /** * Helper Class to initiate SwingWorker */ class MrDLibFetcherWorker extends SwingWorker<List<BibEntry>, Void> { private final MrDLibFetcher fetcher; private final JabRefPreferences prefs = JabRefPreferences.getInstance(); private final BibEntry selectedEntry; public MrDLibFetcherWorker(BibEntry selectedEntry) throws Exception { this.selectedEntry = selectedEntry; fetcher = new MrDLibFetcher(prefs.get(JabRefPreferences.LANGUAGE), Globals.BUILD_INFO.getVersion().getFullVersion()); } @Override protected List<BibEntry> doInBackground() throws Exception { return fetcher.performSearch(selectedEntry); } } }