package org.jabref.gui.worker;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
import org.jabref.Globals;
import org.jabref.gui.BasePanel;
import org.jabref.gui.ClipBoardManager;
import org.jabref.gui.exporter.RtfTransferable;
import org.jabref.gui.fieldeditors.HtmlTransferable;
import org.jabref.gui.fieldeditors.XmlTransferable;
import org.jabref.logic.citationstyle.CitationStyle;
import org.jabref.logic.citationstyle.CitationStyleGenerator;
import org.jabref.logic.citationstyle.CitationStyleOutputFormat;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.layout.Layout;
import org.jabref.logic.layout.LayoutFormatterPreferences;
import org.jabref.logic.layout.LayoutHelper;
import org.jabref.logic.util.OS;
import org.jabref.model.entry.BibEntry;
import org.jabref.preferences.PreviewPreferences;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Copies the selected entries and formats them with the selected citation style (or preview), then it is copied to the clipboard.
* This worker cannot be reused.
*/
public class CitationStyleToClipboardWorker extends SwingWorker<List<String>, Void> {
private static final Log LOGGER = LogFactory.getLog(CitationStyleToClipboardWorker.class);
private final BasePanel basePanel;
private final List<BibEntry> selectedEntries;
private final String style;
private final String previewStyle;
private final CitationStyleOutputFormat outputFormat;
public CitationStyleToClipboardWorker(BasePanel basePanel, CitationStyleOutputFormat outputFormat) {
this.basePanel = basePanel;
this.selectedEntries = basePanel.getSelectedEntries();
PreviewPreferences previewPreferences = Globals.prefs.getPreviewPreferences();
this.style = previewPreferences.getPreviewCycle().get(previewPreferences.getPreviewCyclePosition());
this.previewStyle = Globals.prefs.getPreviewPreferences().getPreviewStyle();
this.outputFormat = outputFormat;
basePanel.frame().setStatus(Localization.lang("Copying..."));
}
@Override
protected List<String> doInBackground() throws Exception {
if (CitationStyle.isCitationStyleFile(style)) {
return CitationStyleGenerator.generateCitations(selectedEntries, style, outputFormat);
} else {
StringReader sr = new StringReader(previewStyle.replace("__NEWLINE__", "\n"));
LayoutFormatterPreferences layoutFormatterPreferences = Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader);
Layout layout = new LayoutHelper(sr, layoutFormatterPreferences).getLayoutFromText();
List<String> citations = new ArrayList<>(selectedEntries.size());
for (BibEntry entry : selectedEntries) {
citations.add(layout.doLayout(entry, basePanel.getDatabase()));
}
return citations;
}
}
@Override
public void done() {
try {
List<String> citations = get();
// if it's not a citation style take care of the preview
if (!CitationStyle.isCitationStyleFile(style)) {
new ClipBoardManager().setTransferableClipboardContents(processPreview(citations));
} else {
// if it's generated by a citation style take care of each output format
Transferable transferable;
switch (outputFormat) {
case HTML:
transferable = processHtml(citations);
break;
case RTF:
transferable = processRtf(citations);
break;
case XSL_FO:
transferable = processXslFo(citations);
break;
case ASCII_DOC:
case TEXT:
transferable = processText(citations);
break;
default:
LOGGER.warn("unknown output format: '" + outputFormat + "', processing it via the default.");
transferable = processText(citations);
break;
}
new ClipBoardManager().setTransferableClipboardContents(transferable);
}
basePanel.frame().setStatus(Localization.lang("Copied %0 citations.", String.valueOf(selectedEntries.size())));
} catch (InterruptedException | ExecutionException e) {
LOGGER.error("Error while copying citations to the clipboard", e);
}
}
/**
* Generates a plain text string out of the preview and copies it additionally to the html to the clipboard
* (WYSIWYG Editors use the HTML, plain text editors the text)
*/
protected static HtmlTransferable processPreview(List<String> citations) {
String html = String.join(CitationStyleOutputFormat.HTML.getLineSeparator(), citations);
return new HtmlTransferable(html);
}
/**
* Joins every citation with a newline and returns it.
*/
protected static StringSelection processText(List<String> citations) {
return new StringSelection(String.join(CitationStyleOutputFormat.TEXT.getLineSeparator(), citations));
}
/**
* Converts the citations into the RTF format.
*/
protected static RtfTransferable processRtf(List<String> citations) {
String result = "{\\rtf" + OS.NEWLINE +
String.join(CitationStyleOutputFormat.RTF.getLineSeparator(), citations) +
"}";
return new RtfTransferable(result);
}
/**
* Inserts each citation into a XLSFO body and copies it to the clipboard
*/
protected static XmlTransferable processXslFo(List<String> citations) {
String result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + OS.NEWLINE +
"<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">" + OS.NEWLINE +
" <fo:layout-master-set>" + OS.NEWLINE +
" <fo:simple-page-master master-name=\"citations\">" + OS.NEWLINE +
" <fo:region-body/>" + OS.NEWLINE +
" </fo:simple-page-master>" + OS.NEWLINE +
" </fo:layout-master-set>" + OS.NEWLINE +
" <fo:page-sequence master-reference=\"citations\">" + OS.NEWLINE +
" <fo:flow flow-name=\"xsl-region-body\">" + OS.NEWLINE + OS.NEWLINE;
result += String.join(CitationStyleOutputFormat.XSL_FO.getLineSeparator(), citations);
result += OS.NEWLINE +
" </fo:flow>" + OS.NEWLINE +
" </fo:page-sequence>" + OS.NEWLINE +
"</fo:root>" + OS.NEWLINE;
return new XmlTransferable(result);
}
/**
* Inserts each citation into a HTML body and copies it to the clipboard
*/
protected static HtmlTransferable processHtml(List<String> citations) {
String result = "<!DOCTYPE html>" + OS.NEWLINE +
"<html>" + OS.NEWLINE +
" <head>" + OS.NEWLINE +
" <meta charset=\"utf-8\">" + OS.NEWLINE +
" </head>" + OS.NEWLINE +
" <body>" + OS.NEWLINE + OS.NEWLINE;
result += String.join(CitationStyleOutputFormat.HTML.getLineSeparator(), citations);
result += OS.NEWLINE +
" </body>" + OS.NEWLINE +
"</html>" + OS.NEWLINE;
return new HtmlTransferable(result);
}
}