package net.sf.jabref.external; import net.sf.jabref.*; import net.sf.jabref.util.XMPUtil; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.FileListEntry; import javax.swing.*; import java.awt.event.ActionEvent; import java.io.File; import java.util.List; import java.util.ArrayList; /** * Write XMP action for EntryEditor toolbar. */ public class WriteXMPEntryEditorAction extends AbstractAction { private BasePanel panel; private EntryEditor editor; private String message = null; public WriteXMPEntryEditorAction(BasePanel panel, EntryEditor editor) { this.panel = panel; this.editor = editor; putValue(NAME, Globals.lang("Write XMP")); putValue(SMALL_ICON, GUIGlobals.getImage("pdfSmall")); putValue(SHORT_DESCRIPTION, Globals.lang("Write BibtexEntry as XMP-metadata to PDF.")); } public void actionPerformed(ActionEvent actionEvent) { setEnabled(false); panel.output(Globals.lang("Writing XMP metadata...")); panel.frame().setProgressBarIndeterminate(true); panel.frame().setProgressBarVisible(true); BibtexEntry entry = editor.getEntry(); // Make a list of all PDFs linked from this entry: List<File> files = new ArrayList<File>(); // First check the (legacy) "pdf" field: String pdf = entry.getField("pdf"); String dir = panel.metaData().getFileDirectory("pdf"); File f = Util.expandFilename(pdf, new String[]{dir, "."}); if (f != null) files.add(f); // Then check the "file" field: dir = panel.metaData().getFileDirectory(GUIGlobals.FILE_FIELD); String field = entry.getField(GUIGlobals.FILE_FIELD); if (field != null) { FileListTableModel tm = new FileListTableModel(); tm.setContent(field); for (int j = 0; j < tm.getRowCount(); j++) { FileListEntry flEntry = tm.getEntry(j); if ((flEntry.getType() != null) && (flEntry.getType().getName().toLowerCase().equals("pdf"))) { f = Util.expandFilename(flEntry.getLink(), new String[]{dir, "."}); if (f != null) files.add(f); } } } // We want to offload the actual work to a background thread, so we have a worker // thread: AbstractWorker worker = new WriteXMPWorker(files, entry); // Using Spin, we get a thread that gets synchronously offloaded to a new thread, // blocking the execution of this method: worker.getWorker().run(); // After the worker thread finishes, we are unblocked and ready to print the // status message: panel.output(message); panel.frame().setProgressBarVisible(false); setEnabled(true); } class WriteXMPWorker extends AbstractWorker { private List<File> files; private BibtexEntry entry; public WriteXMPWorker(List<File> files, BibtexEntry entry) { this.files = files; this.entry = entry; } public void run() { if (files.size() == 0) { message = Globals.lang("No PDF linked") + ".\n"; } else { int written = 0, error = 0; for (File file : files) { if (!file.exists()) { if (files.size() == 1) message = Globals.lang("PDF does not exist"); error++; } else { try { XMPUtil.writeXMP(file, entry, panel.database()); if (files.size() == 1) message = Globals.lang("Wrote XMP-metadata"); written++; } catch (Exception e) { if (files.size() == 1) message = Globals.lang("Error while writing") + " '" + file.getPath() + "'"; error++; } } } if (files.size() > 1) { StringBuilder sb = new StringBuilder(); sb.append(Globals.lang("Finished writing XMP-metadata. Wrote to %0 file(s).", String.valueOf(written))); if (error > 0) sb.append(" " + Globals.lang("Error writing to %0 file(s).", String.valueOf(error))); message = sb.toString(); } } } } }