net.sf.jabref.pdfimport.PdfImporter.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jabref.pdfimport.PdfImporter.java

Source

/*  Copyright (C) 2003-2015 JabRef contributors.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package net.sf.jabref.pdfimport;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.swing.JOptionPane;

import net.sf.jabref.Globals;
import net.sf.jabref.external.DroppedFileHandler;
import net.sf.jabref.external.ExternalFileTypes;
import net.sf.jabref.gui.BasePanel;
import net.sf.jabref.gui.BasePanelMode;
import net.sf.jabref.gui.EntryTypeDialog;
import net.sf.jabref.gui.FileListEntry;
import net.sf.jabref.gui.FileListTableModel;
import net.sf.jabref.gui.JabRefFrame;
import net.sf.jabref.gui.entryeditor.EntryEditor;
import net.sf.jabref.gui.maintable.MainTable;
import net.sf.jabref.gui.undo.UndoableInsertEntry;
import net.sf.jabref.importer.ParserResult;
import net.sf.jabref.importer.fileformat.PdfContentImporter;
import net.sf.jabref.importer.fileformat.PdfXmpImporter;
import net.sf.jabref.logic.l10n.Localization;
import net.sf.jabref.logic.labelpattern.LabelPatternUtil;
import net.sf.jabref.logic.util.UpdateField;
import net.sf.jabref.logic.util.io.FileUtil;
import net.sf.jabref.logic.xmp.XMPUtil;
import net.sf.jabref.model.database.KeyCollisionException;
import net.sf.jabref.model.entry.BibEntry;
import net.sf.jabref.model.entry.EntryType;
import net.sf.jabref.model.entry.FieldName;
import net.sf.jabref.model.entry.IdGenerator;
import net.sf.jabref.preferences.JabRefPreferences;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class PdfImporter {

    private final JabRefFrame frame;
    private final BasePanel panel;
    private final MainTable entryTable;
    private final int dropRow;

    private static final Log LOGGER = LogFactory.getLog(PdfImporter.class);

    /**
     * Creates the PdfImporter
     *
     * @param frame the JabRef frame
     * @param panel the panel to use
     * @param entryTable the entry table to work on
     * @param dropRow the row the entry is dropped to. May be -1 to indicate that no row is selected.
     */
    public PdfImporter(JabRefFrame frame, BasePanel panel, MainTable entryTable, int dropRow) {
        this.frame = frame;
        this.panel = panel;
        this.entryTable = entryTable;
        this.dropRow = dropRow;
    }

    public class ImportPdfFilesResult {

        private final List<String> noPdfFiles;
        private final List<BibEntry> entries;

        public ImportPdfFilesResult(List<String> noPdfFiles, List<BibEntry> entries) {
            this.noPdfFiles = noPdfFiles;
            this.entries = entries;
        }

        public List<String> getNoPdfFiles() {
            return noPdfFiles;
        }

        public List<BibEntry> getEntries() {
            return entries;
        }
    }

    /**
     *
     * Imports the PDF files given by fileNames
     *
     * @param fileNames states the names of the files to import
     * @return list of successful created BibTeX entries and list of non-PDF files
     */
    public ImportPdfFilesResult importPdfFiles(String[] fileNames) {
        // sort fileNames in PDFfiles to import and other files
        // PDFfiles: variable files
        // other files: variable noPdfFiles
        List<String> files = new ArrayList<>(Arrays.asList(fileNames));
        List<String> noPdfFiles = new ArrayList<>();
        PdfFileFilter pdfFilter = PdfFileFilter.INSTANCE;
        for (String file : files) {
            if (!pdfFilter.accept(file)) {
                noPdfFiles.add(file);
            }
        }
        files.removeAll(noPdfFiles);
        // files and noPdfFiles correctly sorted

        // import the files
        List<BibEntry> entries = importPdfFiles(files);

        return new ImportPdfFilesResult(noPdfFiles, entries);
    }

    /**
     * @param fileNames - PDF files to import
     * @return true if the import succeeded, false otherwise
     */
    private List<BibEntry> importPdfFiles(List<String> fileNames) {
        if (panel == null) {
            return Collections.emptyList();
        }
        ImportDialog importDialog = null;
        boolean doNotShowAgain = false;
        boolean neverShow = Globals.prefs.getBoolean(JabRefPreferences.PREF_IMPORT_ALWAYSUSE);
        int globalChoice = Globals.prefs.getInt(JabRefPreferences.PREF_IMPORT_DEFAULT_PDF_IMPORT_STYLE);

        List<BibEntry> res = new ArrayList<>();

        for (String fileName : fileNames) {
            if (!neverShow && !doNotShowAgain) {
                importDialog = new ImportDialog(dropRow >= 0, fileName);
                if (!XMPUtil.hasMetadata(Paths.get(fileName), Globals.prefs)) {
                    importDialog.disableXMPChoice();
                }
                importDialog.setLocationRelativeTo(frame);
                importDialog.showDialog();
                doNotShowAgain = importDialog.isDoNotShowAgain();
            }
            if (neverShow || (importDialog.getResult() == JOptionPane.OK_OPTION)) {
                int choice = neverShow ? globalChoice : importDialog.getChoice();
                switch (choice) {
                case ImportDialog.XMP:
                    doXMPImport(fileName, res);
                    break;

                case ImportDialog.CONTENT:
                    doContentImport(fileName, res);
                    break;
                case ImportDialog.NOMETA:
                    BibEntry entry = createNewBlankEntry(fileName);
                    res.add(entry);
                    break;
                case ImportDialog.ONLYATTACH:
                    DroppedFileHandler dfh = new DroppedFileHandler(frame, panel);
                    dfh.linkPdfToEntry(fileName, entryTable, dropRow);
                    break;
                default:
                    break;
                }
            }

        }
        return res;
    }

    private void doXMPImport(String fileName, List<BibEntry> res) {
        List<BibEntry> localRes = new ArrayList<>();
        PdfXmpImporter importer = new PdfXmpImporter();
        Path filePath = Paths.get(fileName);
        ParserResult result = importer.importDatabase(filePath, Globals.prefs.getDefaultEncoding());
        if (result.hasWarnings()) {
            frame.showMessage(result.getErrorMessage());
        }
        localRes.addAll(result.getDatabase().getEntries());

        BibEntry entry;
        if (localRes.isEmpty()) {
            // import failed -> generate default entry
            LOGGER.info("Import failed");
            entry = createNewBlankEntry(fileName);
            res.add(entry);
            return;
        }

        // only one entry is imported
        entry = localRes.get(0);

        // insert entry to database and link file
        panel.getDatabase().insertEntry(entry);
        panel.markBaseChanged();
        FileListTableModel tm = new FileListTableModel();
        File toLink = new File(fileName);
        // Get a list of file directories:
        List<String> dirsS = panel.getBibDatabaseContext().getFileDirectory();

        tm.addEntry(0, new FileListEntry(toLink.getName(), FileUtil.shortenFileName(toLink, dirsS).getPath(),
                ExternalFileTypes.getInstance().getExternalFileTypeByName("PDF")));
        entry.setField(FieldName.FILE, tm.getStringRepresentation());
        res.add(entry);

    }

    private BibEntry createNewBlankEntry(String fileName) {
        BibEntry newEntry = createNewEntry();
        if (newEntry != null) {
            DroppedFileHandler dfh = new DroppedFileHandler(frame, panel);
            dfh.linkPdfToEntry(fileName, newEntry);
        }
        return newEntry;
    }

    private void doContentImport(String fileName, List<BibEntry> res) {

        PdfContentImporter contentImporter = new PdfContentImporter();
        Path filePath = Paths.get(fileName);
        ParserResult result = contentImporter.importDatabase(filePath, Globals.prefs.getDefaultEncoding());
        if (result.hasWarnings()) {
            frame.showMessage(result.getErrorMessage());
        }

        if (!result.getDatabase().hasEntries()) {
            // import failed -> generate default entry
            BibEntry entry = createNewBlankEntry(fileName);
            res.add(entry);
            return;
        }

        // only one entry is imported
        BibEntry entry = result.getDatabase().getEntries().get(0);

        // insert entry to database and link file
        panel.getDatabase().insertEntry(entry);
        panel.markBaseChanged();
        LabelPatternUtil.makeLabel(panel.getBibDatabaseContext().getMetaData(), panel.getDatabase(), entry,
                Globals.prefs);
        DroppedFileHandler dfh = new DroppedFileHandler(frame, panel);
        dfh.linkPdfToEntry(fileName, entry);
        panel.highlightEntry(entry);
        if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_OPEN_FORM)) {
            EntryEditor editor = panel.getEntryEditor(entry);
            panel.showEntryEditor(editor);
            panel.adjustSplitter();
        }
        res.add(entry);
    }

    private BibEntry createNewEntry() {
        // Find out what type is desired
        EntryTypeDialog etd = new EntryTypeDialog(frame);
        // We want to center the dialog, to make it look nicer.
        etd.setLocationRelativeTo(frame);
        etd.setVisible(true);
        EntryType type = etd.getChoice();

        if (type != null) { // Only if the dialog was not canceled.
            String id = IdGenerator.next();
            final BibEntry be = new BibEntry(id, type.getName());
            try {
                panel.getDatabase().insertEntry(be);

                // Set owner/timestamp if options are enabled:
                List<BibEntry> list = new ArrayList<>();
                list.add(be);
                UpdateField.setAutomaticFields(list, true, true);

                // Create an UndoableInsertEntry object.
                panel.getUndoManager().addEdit(new UndoableInsertEntry(panel.getDatabase(), be, panel));
                panel.output(Localization.lang("Added new") + " '" + type.getName().toLowerCase() + "' "
                        + Localization.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() != BasePanelMode.SHOWING_EDITOR) {
                    panel.setMode(BasePanelMode.WILL_SHOW_EDITOR);
                }

                panel.showEntry(be);

                // The database just changed.
                panel.markBaseChanged();

                return be;
            } catch (KeyCollisionException ex) {
                LOGGER.info("Key collision occurred", ex);
            }
        }
        return null;
    }
}