package spl; import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.*; import net.sf.jabref.*; import net.sf.jabref.external.DroppedFileHandler; import net.sf.jabref.external.ExternalFileType; import net.sf.jabref.gui.FileListEditor; import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.MainTable; import net.sf.jabref.imports.ImportMenuItem; import net.sf.jabref.imports.PdfContentImporter; import net.sf.jabref.imports.PdfXmpImporter; import net.sf.jabref.labelPattern.LabelPatternUtil; import net.sf.jabref.undo.UndoableInsertEntry; import net.sf.jabref.util.XMPUtil; import org.sciplore.beans.Document; import spl.filter.PdfFileFilter; import spl.gui.ImportDialog; import spl.gui.MetaDataListDialog; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; /** * Created by IntelliJ IDEA. * User: Christoph Arbeit * Date: 08.09.2010 * Time: 14:49:08 * To change this template use File | Settings | File Templates. */ public class PdfImporter { private JabRefFrame frame; private BasePanel panel; private MainTable entryTable; private int dropRow; public PdfImporter(JabRefFrame frame, BasePanel panel, MainTable entryTable, int dropRow) { this.frame = frame; this.panel = panel; this.entryTable = entryTable; this.dropRow = dropRow; } /** * * Imports the PDF files given by fileNames * * @param fileNames states the names of the files to import * @return list of non-PDF files */ public String[] importPdfFiles(String[] fileNames, OutputPrinter status){ List<String> files = new ArrayList<String>(Arrays.asList(fileNames)); List<String> noPdfFiles = new ArrayList<String>(); PdfFileFilter pdfFilter = new PdfFileFilter(); for(String file : files){ if(!pdfFilter.accept(file)){ noPdfFiles.add(file); } } files.removeAll(noPdfFiles); importPdfFiles(files, status); String[] noPdfFilesArray = new String[noPdfFiles.size()]; noPdfFiles.toArray(noPdfFilesArray); return noPdfFilesArray; } /** * @param fileNames - PDF files to import * @return true if the import succeeded, false otherwise */ private boolean importPdfFiles(List<String> fileNames, OutputPrinter status){ if(panel == null) return false; ImportDialog importDialog = null; boolean doNotShowAgain = false; boolean neverShow = Globals.prefs.getBoolean(ImportSettingsTab.PREF_IMPORT_ALWAYSUSE); int globalChoice = Globals.prefs.getInt(ImportSettingsTab.PREF_IMPORT_DEFAULT_PDF_IMPORT_STYLE); // Get a list of file directories: ArrayList<File> dirs = new ArrayList<File>(); String[] dirsS = panel.metaData().getFileDirectory(GUIGlobals.FILE_FIELD); for (int i=0; i<dirsS.length; i++) { dirs.add(new File(dirsS[i])); } for(String fileName : fileNames){ List<BibtexEntry> xmpEntriesInFile = readXmpEntries(fileName); if (!neverShow && !doNotShowAgain) { importDialog = new ImportDialog(dropRow, fileName); if(!hasXmpEntries(xmpEntriesInFile)){ importDialog.disableXMPChoice(); } Tools.centerRelativeToWindow(importDialog, frame); importDialog.showDialog(); doNotShowAgain = importDialog.getDoNotShowAgain(); } if (neverShow || (importDialog.getResult() == JOptionPane.OK_OPTION)) { int choice = (neverShow?globalChoice:importDialog.getChoice()); DroppedFileHandler dfh; BibtexEntry entry; BibtexEntryType type; InputStream in = null; List<BibtexEntry> res = null; MetaDataListDialog metaDataListDialog; switch (choice) { case ImportDialog.XMP: //SplDatabaseChangeListener dataListener = new SplDatabaseChangeListener(frame, panel, entryTable, fileName); //panel.database().addDatabaseChangeListener(dataListener); //ImportMenuItem importer = new ImportMenuItem(frame, (entryTable == null)); PdfXmpImporter importer = new PdfXmpImporter(); try { in = new FileInputStream(fileName); res = importer.importEntries(in, frame); //importer.automatedImport(new String[]{ fileName }); } catch (IOException ex) { ex.printStackTrace(); } finally { try { in.close(); } catch (Exception f) {} } // import failed -> generate default entry if ((res == null) || (res.size() == 0)) { createNewBlankEntry(fileName); return true; } // only one entry is imported entry = res.get(0); // insert entry to database and link file panel.database().insertEntry(entry); panel.markBaseChanged(); FileListTableModel tm = new FileListTableModel(); File toLink = new File(fileName); tm.addEntry(0, new FileListEntry(toLink.getName(), FileListEditor.relativizePath(toLink, dirs).getPath(), Globals.prefs.getExternalFileTypeByName("pdf"))); entry.setField(GUIGlobals.FILE_FIELD, tm.getStringRepresentation()); break; case ImportDialog.CONTENT: PdfContentImporter contentImporter = new PdfContentImporter(); File file = new File (fileName); try { in = new FileInputStream(file); } catch (Exception e) { // import failed -> generate default entry Globals.logger(Globals.lang("Import failed")); e.printStackTrace(); createNewBlankEntry(fileName); return true; } try { res = contentImporter.importEntries(in, status); } catch (Exception e) { // import failed -> generate default entry Globals.logger(Globals.lang("Import failed")); e.printStackTrace(); createNewBlankEntry(fileName); return true; } finally { try { in.close(); } catch (Exception f) {} } // import failed -> generate default entry if ((res == null) || (res.size() == 0)) { createNewBlankEntry(fileName); return true; } // only one entry is imported entry = res.get(0); // insert entry to database and link file panel.database().insertEntry(entry); panel.markBaseChanged(); LabelPatternUtil.makeLabel(panel.metaData(), panel.database(), entry); dfh = new DroppedFileHandler(frame, panel); dfh.linkPdfToEntry(fileName, entryTable, entry); panel.highlightEntry(entry); if (Globals.prefs.getBoolean("autoOpenForm")) { EntryEditor editor = panel.getEntryEditor(entry); panel.showEntryEditor(editor); panel.adjustSplitter(); } break; case ImportDialog.MRDLIB: metaDataListDialog = new MetaDataListDialog(fileName, true); Tools.centerRelativeToWindow(metaDataListDialog, frame); metaDataListDialog.showDialog(); Document document = metaDataListDialog.getXmlDocuments(); if(document != null /*&& documents.getDocuments() != null && documents.getDocuments().size() > 0*/ && metaDataListDialog.getResult() == JOptionPane.OK_OPTION){ int selected = metaDataListDialog.getTableMetadata().getSelectedRow(); if(selected > -1 /*&& selected < documents.getDocuments().size()*/){ //Document document = documents/*.getDocuments().get(selected)*/; String id = Util.createNeutralId(); entry = new BibtexEntry(id); if(fieldExists(document.getType())){ type = BibtexEntryType.getStandardType(document.getType()); if(type == null){ type = BibtexEntryType.ARTICLE; } entry.setType(type); } else{ entry.setType(BibtexEntryType.ARTICLE); } ArrayList<BibtexEntry> list = new ArrayList<BibtexEntry>(); list.add(entry); Util.setAutomaticFields(list, true, true, false); //insertFields(entry.getRequiredFields(), entry, document); insertFields(BibtexFields.getAllFieldNames(), entry, document); //insertFields(entry.getOptionalFields(), entry, document); panel.database().insertEntry(entry); dfh = new DroppedFileHandler(frame, panel); dfh.linkPdfToEntry(fileName, entryTable, entry); LabelPatternUtil.makeLabel(panel.metaData(), panel.database(), entry); } else{ createNewBlankEntry(fileName); } } else if(metaDataListDialog.getResult() == JOptionPane.CANCEL_OPTION ){ continue; } else if(metaDataListDialog.getResult() == JOptionPane.NO_OPTION ){ createNewBlankEntry(fileName); } else if(document == null /*|| document.getDocuments() == null || document.getDocuments().size() <= 0*/ && metaDataListDialog.getResult() == JOptionPane.OK_OPTION){ createNewBlankEntry(fileName); } break; case ImportDialog.NOMETA: createNewBlankEntry(fileName); break; case ImportDialog.UPDATEEMPTYFIELDS: metaDataListDialog = new MetaDataListDialog(fileName, false); Tools.centerRelativeToWindow(metaDataListDialog, frame); metaDataListDialog.showDialog(); document = metaDataListDialog.getXmlDocuments(); if(document != null /*&& document.getDocuments() != null && document.getDocuments().size() > 0*/ && metaDataListDialog.getResult() == JOptionPane.OK_OPTION){ int selected = metaDataListDialog.getTableMetadata().getSelectedRow(); if(selected > -1 /*&& selected < document.getDocuments().size()*/){ //XmlDocument document = documents.getDocuments().get(selected); entry = entryTable.getEntryAt(dropRow); if(fieldExists(document.getType())){ type = BibtexEntryType.getStandardType(document.getType()); if(type != null){ entry.setType(type); } } //insertFields(entry.getRequiredFields(), entry, document); insertFields(BibtexFields.getAllFieldNames(), entry, document); //insertFields(entry.getOptionalFields(), entry, document); dfh = new DroppedFileHandler(frame, panel); dfh.linkPdfToEntry(fileName, entryTable, dropRow); } } break; case ImportDialog.ONLYATTACH: dfh = new DroppedFileHandler(frame, panel); dfh.linkPdfToEntry(fileName, entryTable, dropRow); break; } } } return true; } private void createNewBlankEntry(String fileName) { BibtexEntry newEntry = createNewEntry(); if(newEntry != null){ DroppedFileHandler dfh = new DroppedFileHandler(frame, panel); dfh.linkPdfToEntry(fileName, entryTable, newEntry); } } private void insertFields(String[] fields, BibtexEntry entry, Document xmlDocument) { DocumentWrapper document = new DocumentWrapper(xmlDocument); for(String field : fields){ if(entry.getField(field) != null){ continue; } if(field.equalsIgnoreCase("author")){ entry.setField(field, document.getAuthors("and")); } if(field.equalsIgnoreCase("title")){ entry.setField(field, document.getTitle()); } if(field.equalsIgnoreCase("abstract")){ entry.setField(field, document.getAbstract()); } /*if(field.equalsIgnoreCase("keywords")){ entry.setField(field, document.getKeyWords()); }*/ if(field.equalsIgnoreCase("doi")){ entry.setField(field, document.getDoi()); } /*if(field.equalsIgnoreCase("pages")){ entry.setField(field, document.getPages()); } if(field.equalsIgnoreCase("volume")){ entry.setField(field, document.getVolume()); } if(field.equalsIgnoreCase("number")){ entry.setField(field, document.getNumber()); }*/ if(field.equalsIgnoreCase("year")){ entry.setField(field, document.getYear()); } /*if(field.equalsIgnoreCase("month")){ entry.setField(field, document.getMonth()); } if(field.equalsIgnoreCase("day")){ entry.setField(field, document.getDay()); } if(field.equalsIgnoreCase("booktitle")){ entry.setField(field, document.getVenue()); } if(field.equalsIgnoreCase("journal")){ entry.setField(field, document.getVenue()); }*/ } } private boolean fieldExists(String string) { return string != null && !string.isEmpty(); } private BibtexEntry createNewEntry() { // Find out what type is wanted. EntryTypeDialog etd = new EntryTypeDialog(frame); // We want to center the dialog, to make it look nicer. Util.placeDialog(etd, frame); etd.setVisible(true); BibtexEntryType type = etd.getChoice(); if (type != null) { // Only if the dialog was not cancelled. String id = Util.createNeutralId(); final BibtexEntry be = new BibtexEntry(id, type); try { panel.database().insertEntry(be); // Set owner/timestamp if options are enabled: ArrayList<BibtexEntry> list = new ArrayList<BibtexEntry>(); list.add(be); Util.setAutomaticFields(list, true, true, false); // Create an UndoableInsertEntry object. panel.undoManager.addEdit(new UndoableInsertEntry(panel.database(), be, panel)); panel.output(Globals.lang("Added new")+" '"+type.getName().toLowerCase()+"' " +Globals.lang("entry")+"."); // We are going to select the new entry. Before that, make sure that we are in // show-entry mode. If we aren't already in that mode, enter the WILL_SHOW_EDITOR // mode which makes sure the selection will trigger display of the entry editor // and adjustment of the splitter. if (panel.getMode() != panel.SHOWING_EDITOR) { panel.setMode(panel.WILL_SHOW_EDITOR); } /*int row = entryTable.findEntry(be); if (row >= 0) // Selects the entry. The selection listener will open the editor. if (row >= 0) { try{ entryTable.setRowSelectionInterval(row, row); }catch(IllegalArgumentException e){ System.out.println("RowCount: " + entryTable.getRowCount()); } //entryTable.setActiveRow(row); entryTable.ensureVisible(row); } else { // The entry is not visible in the table, perhaps due to a filtering search // or group selection. Show the entry editor anyway: panel.showEntry(be); } */ panel.showEntry(be); panel.markBaseChanged(); // The database just changed. new FocusRequester(panel.getEntryEditor(be)); return be; } catch (KeyCollisionException ex) { Util.pr(ex.getMessage()); } } return null; } private List<BibtexEntry> readXmpEntries(String fileName){ List<BibtexEntry> xmpEntriesInFile = null; try { xmpEntriesInFile = XMPUtil.readXMP(fileName); } catch (Exception e) { // Todo Logging } return xmpEntriesInFile; } private boolean hasXmpEntries(List<BibtexEntry> xmpEntriesInFile){ if ((xmpEntriesInFile == null) || (xmpEntriesInFile.size() == 0)) { return false; } else{ return true; } } public MainTable getEntryTable() { return entryTable; } public void setEntryTable(MainTable entryTable) { this.entryTable = entryTable; } public int getDropRow() { return dropRow; } public void setDropRow(int dropRow) { this.dropRow = dropRow; } }