Search in sources :

Example 1 with LinkedFile

use of org.jabref.model.entry.LinkedFile in project jabref by JabRef.

the class LinkedFilesEditorViewModel method fromFile.

/**
     * Creates an instance of {@link LinkedFile} based on the given file.
     * We try to guess the file type and relativize the path against the given file directories.
     *
     * TODO: Move this method to {@link LinkedFile} as soon as {@link ExternalFileType} lives in model.
     */
private static LinkedFile fromFile(Path file, List<Path> fileDirectories) {
    String fileExtension = FileHelper.getFileExtension(file).orElse("");
    ExternalFileType suggestedFileType = ExternalFileTypes.getInstance().getExternalFileTypeByExt(fileExtension).orElse(new UnknownExternalFileType(fileExtension));
    Path relativePath = FileUtil.shortenFileName(file, fileDirectories);
    return new LinkedFile("", relativePath.toString(), suggestedFileType.getName());
}
Also used : UnknownExternalFileType(org.jabref.gui.externalfiletype.UnknownExternalFileType) ExternalFileType(org.jabref.gui.externalfiletype.ExternalFileType) Path(java.nio.file.Path) LinkedFile(org.jabref.model.entry.LinkedFile) UnknownExternalFileType(org.jabref.gui.externalfiletype.UnknownExternalFileType)

Example 2 with LinkedFile

use of org.jabref.model.entry.LinkedFile in project jabref by JabRef.

the class MoveFileAction method actionPerformed.

@Override
public void actionPerformed(ActionEvent event) {
    int selected = editor.getSelectedRow();
    if (selected == -1) {
        return;
    }
    FileListEntry entry = editor.getTableModel().getEntry(selected);
    LinkedFile field = entry.toParsedFileField();
    if (field.isOnlineLink()) {
        // TODO: notify that this operation cannot be done on remote links
        return;
    }
    // Get an absolute path representation:
    Optional<Path> fileDir = frame.getCurrentBasePanel().getBibDatabaseContext().getFirstExistingFileDir(Globals.prefs.getFileDirectoryPreferences());
    if (!fileDir.isPresent()) {
        JOptionPane.showMessageDialog(frame, Localization.lang("File directory is not set or does not exist!"), Localization.lang("Move file"), JOptionPane.ERROR_MESSAGE);
        return;
    }
    // Check if the current file exists:
    Optional<Path> file = field.findIn(frame.getCurrentBasePanel().getBibDatabaseContext(), Globals.prefs.getFileDirectoryPreferences());
    if ((file.isPresent()) && Files.exists(file.get())) {
        MoveFilesCleanup moveFiles = new MoveFilesCleanup(frame.getCurrentBasePanel().getBibDatabaseContext(), Globals.prefs.getCleanupPreferences(Globals.journalAbbreviationLoader).getFileDirPattern(), Globals.prefs.getFileDirectoryPreferences(), Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader), field);
        String[] options = { Localization.lang("Move file"), Localization.lang("Cancel") };
        int dialogResult = JOptionPane.showOptionDialog(frame, Localization.lang("Move file to file directory?") + " " + fileDir.get(), Localization.lang("Move file"), JOptionPane.INFORMATION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[0]);
        if (dialogResult == JOptionPane.YES_OPTION) {
            moveFiles.cleanup((eEditor.getEntry()));
        }
    } else {
        // File doesn't exist, so we can't move it.
        JOptionPane.showMessageDialog(frame, Localization.lang("Could not find file '%0'.", entry.getLink()), Localization.lang("File not found"), JOptionPane.ERROR_MESSAGE);
    }
}
Also used : Path(java.nio.file.Path) LinkedFile(org.jabref.model.entry.LinkedFile) MoveFilesCleanup(org.jabref.logic.cleanup.MoveFilesCleanup) FileListEntry(org.jabref.gui.filelist.FileListEntry)

Example 3 with LinkedFile

use of org.jabref.model.entry.LinkedFile in project jabref by JabRef.

the class RenameFileAction method actionPerformed.

@Override
public void actionPerformed(ActionEvent e) {
    int selected = editor.getSelectedRow();
    if (selected == -1) {
        return;
    }
    FileListEntry entry = editor.getTableModel().getEntry(selected);
    LinkedFile field = entry.toParsedFileField();
    // Check if the current file exists:
    if (field.isOnlineLink()) {
        // TODO: notify that this operation cannot be done on remote links
        return;
    }
    Optional<Path> fileDir = frame.getCurrentBasePanel().getBibDatabaseContext().getFirstExistingFileDir(Globals.prefs.getFileDirectoryPreferences());
    if (!fileDir.isPresent()) {
        JOptionPane.showMessageDialog(frame, Localization.lang("File directory is not set or does not exist!"), Localization.lang("Rename file"), JOptionPane.ERROR_MESSAGE);
        return;
    }
    Optional<Path> file = field.findIn(frame.getCurrentBasePanel().getBibDatabaseContext(), Globals.prefs.getFileDirectoryPreferences());
    if ((file.isPresent()) && Files.exists(file.get())) {
        RenamePdfCleanup pdfCleanup = new RenamePdfCleanup(false, frame.getCurrentBasePanel().getBibDatabaseContext(), Globals.prefs.getCleanupPreferences(Globals.journalAbbreviationLoader).getFileNamePattern(), Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader), Globals.prefs.getFileDirectoryPreferences(), field);
        String targetFileName = pdfCleanup.getTargetFileName(field, eEditor.getEntry());
        String[] options = { Localization.lang("Rename file"), Localization.lang("Cancel") };
        int dialogResult = JOptionPane.showOptionDialog(frame, Localization.lang("Rename file to") + " " + targetFileName, Localization.lang("Rename file"), JOptionPane.INFORMATION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[0]);
        //indicates Rename pressed
        if (dialogResult == JOptionPane.YES_OPTION) {
            pdfCleanup.cleanup(eEditor.getEntry());
        }
    }
}
Also used : Path(java.nio.file.Path) LinkedFile(org.jabref.model.entry.LinkedFile) FileListEntry(org.jabref.gui.filelist.FileListEntry) RenamePdfCleanup(org.jabref.logic.cleanup.RenamePdfCleanup)

Example 4 with LinkedFile

use of org.jabref.model.entry.LinkedFile in project jabref by JabRef.

the class SynchronizeFileField method run.

@Override
public void run() {
    if (!goOn) {
        panel.output(Localization.lang("This operation requires one or more entries to be selected."));
        return;
    }
    entriesChangedCount = 0;
    panel.frame().setProgressBarValue(0);
    panel.frame().setProgressBarVisible(true);
    // autoSet takes 10 (?) times longer than checkExisting
    int weightAutoSet = 10;
    int progressBarMax = (autoSet ? weightAutoSet * sel.size() : 0) + (checkExisting ? sel.size() : 0);
    panel.frame().setProgressBarMaximum(progressBarMax);
    int progress = 0;
    final NamedCompound ce = new NamedCompound(Localization.lang("Automatically set file links"));
    Set<BibEntry> changedEntries = new HashSet<>();
    // First we try to autoset fields
    if (autoSet) {
        List<BibEntry> entries = new ArrayList<>(sel);
        // Start the automatically setting process:
        Runnable r = AutoSetLinks.autoSetLinks(entries, ce, changedEntries, null, panel.getBibDatabaseContext(), null, null);
        JabRefExecutorService.INSTANCE.executeAndWait(r);
    }
    progress += sel.size() * weightAutoSet;
    panel.frame().setProgressBarValue(progress);
    // The following loop checks all external links that are already set.
    if (checkExisting) {
        boolean removeAllBroken = false;
        mainLoop: for (BibEntry aSel : sel) {
            panel.frame().setProgressBarValue(progress++);
            final Optional<String> old = aSel.getField(FieldName.FILE);
            // Check if a extension is set:
            if (old.isPresent() && !(old.get().isEmpty())) {
                FileListTableModel tableModel = new FileListTableModel();
                tableModel.setContentDontGuessTypes(old.get());
                for (int j = 0; j < tableModel.getRowCount(); j++) {
                    FileListEntry flEntry = tableModel.getEntry(j);
                    LinkedFile field = flEntry.toParsedFileField();
                    // See if the link looks like an URL:
                    if (field.isOnlineLink()) {
                        // Don't check the remote file.
                        continue;
                    // TODO: should there be an option to check remote links?
                    }
                    // A variable to keep track of whether this link gets deleted:
                    boolean deleted = false;
                    // Get an absolute path representation:
                    Optional<Path> file = field.findIn(panel.getBibDatabaseContext(), Globals.prefs.getFileDirectoryPreferences());
                    if ((!file.isPresent()) || !Files.exists(file.get())) {
                        int answer;
                        if (removeAllBroken) {
                            // We should delete this link.
                            answer = 2;
                        } else {
                            answer = JOptionPane.showOptionDialog(panel.frame(), Localization.lang("<HTML>Could not find file '%0'<BR>linked from entry '%1'</HTML>", flEntry.getLink(), aSel.getCiteKeyOptional().orElse(Localization.lang("undefined"))), Localization.lang("Broken link"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, brokenLinkOptions, brokenLinkOptions[0]);
                        }
                        switch(answer) {
                            case 1:
                                // Assign new file.
                                FileListEntryEditor flEditor = new FileListEntryEditor(panel.frame(), flEntry, false, true, panel.getBibDatabaseContext());
                                flEditor.setVisible(true, true);
                                break;
                            case 2:
                                // Clear field:
                                tableModel.removeEntry(j);
                                // Make sure we don't investigate this link further.
                                deleted = true;
                                // Step back in the iteration, because we removed an entry.
                                j--;
                                break;
                            case 3:
                                // Clear field:
                                tableModel.removeEntry(j);
                                // Make sure we don't investigate this link further.
                                deleted = true;
                                // Step back in the iteration, because we removed an entry.
                                j--;
                                // Notify for further cases.
                                removeAllBroken = true;
                                break;
                            default:
                                // Cancel
                                break mainLoop;
                        }
                    }
                    // Unless we deleted this link, see if its file type is recognized:
                    if (!deleted && flEntry.getType().isPresent() && (flEntry.getType().get() instanceof UnknownExternalFileType)) {
                        String[] options = new String[] { Localization.lang("Define '%0'", flEntry.getType().get().getName()), Localization.lang("Change file type"), Localization.lang("Cancel") };
                        String defOption = options[0];
                        int answer = JOptionPane.showOptionDialog(panel.frame(), Localization.lang("One or more file links are of the type '%0', which is undefined. What do you want to do?", flEntry.getType().get().getName()), Localization.lang("Undefined file type"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, defOption);
                        if (answer == JOptionPane.CANCEL_OPTION) {
                        // User doesn't want to handle this unknown link type.
                        } else if (answer == JOptionPane.YES_OPTION) {
                            // User wants to define the new file type. Show the dialog:
                            ExternalFileType newType = new ExternalFileType(flEntry.getType().get().getName(), "", "", "", "new", IconTheme.JabRefIcon.FILE.getSmallIcon());
                            ExternalFileTypeEntryEditor editor = new ExternalFileTypeEntryEditor(panel.frame(), newType);
                            editor.setVisible(true);
                            if (editor.okPressed()) {
                                // Get the old list of types, add this one, and update the list in prefs:
                                List<ExternalFileType> fileTypes = new ArrayList<>(ExternalFileTypes.getInstance().getExternalFileTypeSelection());
                                fileTypes.add(newType);
                                Collections.sort(fileTypes);
                                ExternalFileTypes.getInstance().setExternalFileTypes(fileTypes);
                                panel.getMainTable().repaint();
                            }
                        } else {
                            // User wants to change the type of this link.
                            // First get a model of all file links for this entry:
                            FileListEntryEditor editor = new FileListEntryEditor(panel.frame(), flEntry, false, true, panel.getBibDatabaseContext());
                            editor.setVisible(true, false);
                        }
                    }
                }
                if (!tableModel.getStringRepresentation().equals(old.orElse(null))) {
                    // The table has been modified. Store the change:
                    String toSet = tableModel.getStringRepresentation();
                    if (toSet.isEmpty()) {
                        ce.addEdit(new UndoableFieldChange(aSel, FieldName.FILE, old.orElse(null), null));
                        aSel.clearField(FieldName.FILE);
                    } else {
                        ce.addEdit(new UndoableFieldChange(aSel, FieldName.FILE, old.orElse(null), toSet));
                        aSel.setField(FieldName.FILE, toSet);
                    }
                    changedEntries.add(aSel);
                }
            }
        }
    }
    if (!changedEntries.isEmpty()) {
        // Add the undo edit:
        ce.end();
        panel.getUndoManager().addEdit(ce);
        panel.markBaseChanged();
        entriesChangedCount = changedEntries.size();
    }
}
Also used : BibEntry(org.jabref.model.entry.BibEntry) FileListTableModel(org.jabref.gui.filelist.FileListTableModel) LinkedFile(org.jabref.model.entry.LinkedFile) ExternalFileTypeEntryEditor(org.jabref.gui.externalfiletype.ExternalFileTypeEntryEditor) Optional(java.util.Optional) ArrayList(java.util.ArrayList) FileListEntry(org.jabref.gui.filelist.FileListEntry) UnknownExternalFileType(org.jabref.gui.externalfiletype.UnknownExternalFileType) UnknownExternalFileType(org.jabref.gui.externalfiletype.UnknownExternalFileType) ExternalFileType(org.jabref.gui.externalfiletype.ExternalFileType) FileListEntryEditor(org.jabref.gui.filelist.FileListEntryEditor) NamedCompound(org.jabref.gui.undo.NamedCompound) UndoableFieldChange(org.jabref.gui.undo.UndoableFieldChange) HashSet(java.util.HashSet)

Example 5 with LinkedFile

use of org.jabref.model.entry.LinkedFile in project jabref by JabRef.

the class RenamePdfCleanup method cleanup.

@Override
public List<FieldChange> cleanup(BibEntry entry) {
    List<LinkedFile> newFileList;
    List<LinkedFile> fileList;
    if (singleFieldCleanup != null) {
        fileList = Arrays.asList(singleFieldCleanup);
        newFileList = entry.getFiles().stream().filter(x -> !x.equals(singleFieldCleanup)).collect(Collectors.toList());
    } else {
        newFileList = new ArrayList<>();
        fileList = entry.getFiles();
    }
    boolean changed = false;
    for (LinkedFile flEntry : fileList) {
        String realOldFilename = flEntry.getLink();
        if (onlyRelativePaths && Paths.get(realOldFilename).isAbsolute()) {
            newFileList.add(flEntry);
            continue;
        }
        //old path and old filename
        Optional<Path> expandedOldFile = flEntry.findIn(databaseContext, fileDirectoryPreferences);
        if ((!expandedOldFile.isPresent()) || (expandedOldFile.get().getParent() == null)) {
            // something went wrong. Just skip this entry
            newFileList.add(flEntry);
            continue;
        }
        String targetFileName = getTargetFileName(flEntry, entry);
        Path newPath = expandedOldFile.get().getParent().resolve(targetFileName);
        String expandedOldFilePath = expandedOldFile.get().toString();
        boolean pathsDifferOnlyByCase = newPath.toString().equalsIgnoreCase(expandedOldFilePath) && !newPath.toString().equals(expandedOldFilePath);
        if (Files.exists(newPath) && !pathsDifferOnlyByCase) {
            // we do not overwrite files
            // Since File.exists is sometimes not case-sensitive, the check pathsDifferOnlyByCase ensures that we
            // nonetheless rename files to a new name which just differs by case.
            // TODO: we could check here if the newPath file is linked with the current entry. And if not, we could add a link
            LOGGER.debug("There already exists a file with that name " + newPath.getFileName() + " so I won't rename it");
            newFileList.add(flEntry);
            continue;
        }
        try {
            if (!Files.exists(newPath)) {
                Files.createDirectories(newPath);
            }
        } catch (IOException e) {
            LOGGER.error("Could not create necessary target directoires for renaming", e);
        }
        boolean renameSuccessful = FileUtil.renameFile(Paths.get(expandedOldFilePath), newPath, true);
        if (renameSuccessful) {
            changed = true;
            //Change the path for this entry
            String description = flEntry.getDescription();
            String type = flEntry.getFileType();
            //We use the file directory (if none is set - then bib file) to create relative file links
            Optional<Path> settingsDir = databaseContext.getFirstExistingFileDir(fileDirectoryPreferences);
            if (settingsDir.isPresent()) {
                Path parent = settingsDir.get();
                String newFileEntryFileName;
                if (parent == null) {
                    newFileEntryFileName = targetFileName;
                } else {
                    newFileEntryFileName = parent.relativize(newPath).toString();
                }
                newFileList.add(new LinkedFile(description, newFileEntryFileName, type));
            }
        } else {
            unsuccessfulRenames++;
        }
    }
    if (changed) {
        Optional<FieldChange> change = entry.setFiles(newFileList);
        //if we put a null undo object here, the change by "doMakePathsRelative" would overwrite the field value nevertheless.
        if (change.isPresent()) {
            return Collections.singletonList(change.get());
        } else {
            return Collections.emptyList();
        }
    }
    return Collections.emptyList();
}
Also used : Path(java.nio.file.Path) LinkedFile(org.jabref.model.entry.LinkedFile) FieldChange(org.jabref.model.FieldChange) IOException(java.io.IOException)

Aggregations

LinkedFile (org.jabref.model.entry.LinkedFile)28 Test (org.junit.Test)13 File (java.io.File)11 Path (java.nio.file.Path)8 FieldChange (org.jabref.model.FieldChange)6 ArrayList (java.util.ArrayList)5 BibEntry (org.jabref.model.entry.BibEntry)5 HashMap (java.util.HashMap)3 List (java.util.List)3 ExternalFileType (org.jabref.gui.externalfiletype.ExternalFileType)3 UnknownExternalFileType (org.jabref.gui.externalfiletype.UnknownExternalFileType)3 FileListEntry (org.jabref.gui.filelist.FileListEntry)3 LayoutFormatterPreferences (org.jabref.logic.layout.LayoutFormatterPreferences)3 IOException (java.io.IOException)2 Paths (java.nio.file.Paths)2 Map (java.util.Map)2 Collectors (java.util.stream.Collectors)2 Log (org.apache.commons.logging.Log)2 LogFactory (org.apache.commons.logging.LogFactory)2 FileFieldParser (org.jabref.model.entry.FileFieldParser)2