private static void fixWrongFileEntries(BibtexEntry entry, NamedCompound ce) { String oldValue = entry.getField(Globals.FILE_FIELD); if (oldValue == null) { return; } FileListTableModel flModel = new FileListTableModel(); flModel.setContent(oldValue); if (flModel.getRowCount() == 0) { return; } boolean changed = false; for (int i = 0; i < flModel.getRowCount(); i++) { FileListEntry flEntry = flModel.getEntry(i); String link = flEntry.getLink(); String description = flEntry.getDescription(); if ("".equals(link) && (!"".equals(description))) { // link and description seem to be switched, quickly fix that flEntry.setLink(flEntry.getDescription()); flEntry.setDescription(""); changed = true; } } if (changed) { String newValue = flModel.getStringRepresentation(); assert (!oldValue.equals(newValue)); entry.setField(Globals.FILE_FIELD, newValue); ce.addEdit(new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue, newValue)); } }
private void doMakePathsRelative(BibtexEntry entry, NamedCompound ce) { String oldValue = entry.getField(Globals.FILE_FIELD); if (oldValue == null) { return; } FileListTableModel flModel = new FileListTableModel(); flModel.setContent(oldValue); if (flModel.getRowCount() == 0) { return; } boolean changed = false; for (int i = 0; i < flModel.getRowCount(); i++) { FileListEntry flEntry = flModel.getEntry(i); String oldFileName = flEntry.getLink(); String newFileName = FileUtil.shortenFileName( new File(oldFileName), panel.metaData().getFileDirectory(Globals.FILE_FIELD)) .toString(); if (!oldFileName.equals(newFileName)) { flEntry.setLink(newFileName); changed = true; } } if (changed) { String newValue = flModel.getStringRepresentation(); assert (!oldValue.equals(newValue)); entry.setField(Globals.FILE_FIELD, newValue); ce.addEdit(new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue, newValue)); } }
@Test @Ignore public void testInsertTestData() throws Exception { entry1 = new BibtexEntry(); JabRefPreferences jabRefPreferences = JabRefPreferences.getInstance(); ExternalFileType fileType = jabRefPreferences.getExternalFileTypeByExt("PDF"); FileListEntry fileListEntry = new FileListEntry("", ImportDataTest.FILE_IN_DATABASE.getAbsolutePath(), fileType); FileListTableModel model = new FileListTableModel(); model.addEntry(0, fileListEntry); entry1.setField("file", model.getStringRepresentation()); database.insertEntry(entry1); // #################### SETUP END ##################### // UnlinkedFilesCrawler crawler = new UnlinkedFilesCrawler(database); CheckableTreeNode treeNode = crawler.searchDirectory(ImportDataTest.EXISTING_FOLDER, new EntryFromPDFCreator()); Assert.assertNotNull(treeNode); /** Select all nodes manually. */ @SuppressWarnings("unchecked") Enumeration<CheckableTreeNode> enumeration = treeNode.breadthFirstEnumeration(); while (enumeration.hasMoreElements()) { CheckableTreeNode nextElement = enumeration.nextElement(); nextElement.setSelected(true); } List<File> resultList = getFileListFromNode(treeNode); Assert.assertFalse(resultList.isEmpty()); Assert.assertTrue(resultList.contains(ImportDataTest.FILE_NOT_IN_DATABASE)); Assert.assertFalse(resultList.contains(ImportDataTest.FILE_IN_DATABASE)); }
private void doRenamePDFs(BibtexEntry entry, NamedCompound ce) { // Extract the path String oldValue = entry.getField(Globals.FILE_FIELD); if (oldValue == null) { return; } FileListTableModel flModel = new FileListTableModel(); flModel.setContent(oldValue); if (flModel.getRowCount() == 0) { return; } boolean changed = false; for (int i = 0; i < flModel.getRowCount(); i++) { String realOldFilename = flModel.getEntry(i).getLink(); if (cleanUpRenamePDFonlyRelativePaths.isSelected() && (new File(realOldFilename).isAbsolute())) { continue; } String newFilename = Util.getLinkedFileName(panel.database(), entry); // String oldFilename = bes.getField(GUIGlobals.FILE_FIELD); // would have to be stored for // undoing purposes // Add extension to newFilename newFilename = newFilename + "." + flModel.getEntry(i).getType().getExtension(); // get new Filename with path // Create new Path based on old Path and new filename File expandedOldFile = FileUtil.expandFilename( realOldFilename, panel.metaData().getFileDirectory(Globals.FILE_FIELD)); if (expandedOldFile.getParent() == null) { // something went wrong. Just skip this entry continue; } String newPath = expandedOldFile .getParent() .concat(System.getProperty("file.separator")) .concat(newFilename); if (new File(newPath).exists()) { // we do not overwrite files // TODO: we could check here if the newPath file is linked with the current entry. And if // not, we could add a link continue; } // do rename boolean renameSuccessful = FileUtil.renameFile(expandedOldFile.toString(), newPath); if (renameSuccessful) { changed = true; // Change the path for this entry String description = flModel.getEntry(i).getDescription(); ExternalFileType type = flModel.getEntry(i).getType(); flModel.removeEntry(i); // we cannot use "newPath" to generate a FileListEntry as newPath is absolute, but we want // to keep relative paths whenever possible File parent = (new File(realOldFilename)).getParentFile(); String newFileEntryFileName; if (parent == null) { newFileEntryFileName = newFilename; } else { newFileEntryFileName = parent.toString().concat(System.getProperty("file.separator")).concat(newFilename); } flModel.addEntry(i, new FileListEntry(description, newFileEntryFileName, type)); } else { unsuccessfulRenames++; } } if (changed) { String newValue = flModel.getStringRepresentation(); assert (!oldValue.equals(newValue)); entry.setField(Globals.FILE_FIELD, newValue); // we put an undo of the field content here // the file is not being renamed back, which leads to inconsistencies // if we put a null undo object here, the change by "doMakePathsRelative" would overwrite the // field value nevertheless. ce.addEdit(new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue, newValue)); } }
@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); int weightAutoSet = 10; // autoSet takes 10 (?) times longer than checkExisting 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) { Collection<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 String old = aSel.getField(Globals.FILE_FIELD); // Check if a extension is set: if ((old != null) && !(old.isEmpty())) { FileListTableModel tableModel = new FileListTableModel(); tableModel.setContentDontGuessTypes(old); // We need to specify which directories to search in for Util.expandFilename: List<String> dirsS = panel.getBibDatabaseContext().getFileDirectory(); List<File> dirs = new ArrayList<>(); for (String dirs1 : dirsS) { dirs.add(new File(dirs1)); } for (int j = 0; j < tableModel.getRowCount(); j++) { FileListEntry flEntry = tableModel.getEntry(j); // See if the link looks like an URL: boolean httpLink = flEntry.link.toLowerCase(Locale.ENGLISH).startsWith("http"); if (httpLink) { continue; // Don't check the remote file. // 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<File> file = FileUtil.expandFilename(flEntry.link, dirsS); if ((!file.isPresent()) || !file.get().exists()) { int answer; if (removeAllBroken) { answer = 2; // We should delete this link. } else { answer = JOptionPane.showOptionDialog( panel.frame(), Localization.lang( "<HTML>Could not find file '%0'<BR>linked from entry '%1'</HTML>", flEntry.link, aSel.getCiteKey()), 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); deleted = true; // Make sure we don't investigate this link further. j--; // Step back in the iteration, because we removed an entry. break; case 3: // Clear field: tableModel.removeEntry(j); deleted = true; // Make sure we don't investigate this link further. j--; // Step back in the iteration, because we removed an entry. removeAllBroken = true; // Notify for further cases. break; default: // Cancel break mainLoop; } } // Unless we deleted this link, see if its file type is recognized: if (!deleted && flEntry.type.isPresent() && (flEntry.type.get() instanceof UnknownExternalFileType)) { String[] options = new String[] { Localization.lang("Define '%0'", flEntry.type.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.type.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.type.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)) { // The table has been modified. Store the change: String toSet = tableModel.getStringRepresentation(); if (toSet.isEmpty()) { ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old, null)); aSel.clearField(Globals.FILE_FIELD); } else { ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old, toSet)); aSel.setField(Globals.FILE_FIELD, toSet); } changedEntries.add(aSel); } } } } if (!changedEntries.isEmpty()) { // Add the undo edit: ce.end(); panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); entriesChangedCount = changedEntries.size(); } }