diff --git a/src/main/java/net/sf/jabref/JabRefPreferences.java b/src/main/java/net/sf/jabref/JabRefPreferences.java index 1fd3fa0553d..0161b79e821 100644 --- a/src/main/java/net/sf/jabref/JabRefPreferences.java +++ b/src/main/java/net/sf/jabref/JabRefPreferences.java @@ -36,12 +36,12 @@ import javax.swing.*; import net.sf.jabref.gui.*; -import net.sf.jabref.gui.actions.CleanUpAction; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; import net.sf.jabref.gui.maintable.PersistenceTableColumnListener; import net.sf.jabref.gui.preftabs.ImportSettingsTab; import net.sf.jabref.importer.fileformat.ImportFormat; import net.sf.jabref.logic.autocompleter.AutoCompletePreferences; +import net.sf.jabref.logic.cleanup.CleanupPreset; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelPattern.GlobalLabelPattern; import net.sf.jabref.logic.util.OS; @@ -310,6 +310,33 @@ public final class JabRefPreferences { public static final String USE_CONVERT_TO_EQUATION = "useConvertToEquation"; public static final String USE_IEEE_ABRV = "useIEEEAbrv"; + public static final String AKS_AUTO_NAMING_PDFS_AGAIN = "AskAutoNamingPDFsAgain"; + public static final String CLEANUP_DOI = "CleanUpDOI"; + public static final String CLEANUP_MONTH = "CleanUpMonth"; + public static final String CLEANUP_PAGE_NUMBERS = "CleanUpPageNumbers"; + public static final String CLEANUP_DATE = "CleanUpDate"; + public static final String CLEANUP_MAKE_PATHS_RELATIVE = "CleanUpMakePathsRelative"; + public static final String CLEANUP_RENAME_PDF = "CleanUpRenamePDF"; + public static final String CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS = "CleanUpRenamePDFonlyRelativePaths"; + public static final String CLEANUP_UPGRADE_EXTERNAL_LINKS = "CleanUpUpgradeExternalLinks"; + public static final String CLEANUP_SUPERSCRIPTS = "CleanUpSuperscripts"; + public static final String CLEANUP_HTML = "CleanUpHTML"; + public static final String CLEANUP_CASE = "CleanUpCase"; + public static final String CLEANUP_LATEX = "CleanUpLaTeX"; + public static final String CLEANUP_UNITS = "CleanUpUnits"; + public static final String CLEANUP_UNICODE = "CleanUpUnicode"; + public static final String CLEANUP_CONVERT_TO_BIBLATEX = "CleanUpConvertToBiblatex"; + public static final String CLEANUP_FIX_FILE_LINKS = "CleanUpFixFileLinks"; + public static final CleanupPreset CLEANUP_DEFAULT_PRESET; + static { + EnumSet deactivedJobs = EnumSet.of( + CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS, + CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS, + CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX); + CLEANUP_DEFAULT_PRESET = new CleanupPreset(EnumSet.complementOf(deactivedJobs)); + } + + public static final String PUSH_TO_APPLICATION = "pushToApplication"; // OpenOffice/LibreOffice preferences @@ -336,6 +363,7 @@ public final class JabRefPreferences { private static final char[][] VALUE_DELIMITERS = new char[][] { {'"', '"'}, {'{', '}'}}; + public String WRAPPED_USERNAME; public final String MARKING_WITH_NUMBER_PATTERN; @@ -729,7 +757,9 @@ private JabRefPreferences() { defaults.put(DB_CONNECT_HOSTNAME, "localhost"); defaults.put(DB_CONNECT_DATABASE, "jabref"); defaults.put(DB_CONNECT_USERNAME, "root"); - CleanUpAction.putDefaults(defaults); + + defaults.put(AKS_AUTO_NAMING_PDFS_AGAIN, Boolean.TRUE); + insertCleanupPreset(defaults, CLEANUP_DEFAULT_PRESET); // defaults for DroppedFileHandler UI defaults.put(DroppedFileHandler.DFH_LEAVE, Boolean.FALSE); @@ -1279,4 +1309,24 @@ public Charset getDefaultEncoding() { public void setDefaultEncoding(Charset encoding) { put(JabRefPreferences.DEFAULT_ENCODING, encoding.name()); } + + private static void insertCleanupPreset(Map storage, CleanupPreset preset) { + + storage.put(CLEANUP_SUPERSCRIPTS, preset.isCleanUpSuperscripts()); + storage.put(CLEANUP_DOI, preset.isCleanUpDOI()); + storage.put(CLEANUP_MONTH, preset.isCleanUpMonth()); + storage.put(CLEANUP_PAGE_NUMBERS, preset.isCleanUpPageNumbers()); + storage.put(CLEANUP_DATE, preset.isCleanUpDate()); + storage.put(CLEANUP_MAKE_PATHS_RELATIVE, preset.isMakePathsRelative()); + storage.put(CLEANUP_RENAME_PDF, preset.isRenamePDF()); + storage.put(CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS, preset.isRenamePdfOnlyRelativePaths()); + storage.put(CLEANUP_UPGRADE_EXTERNAL_LINKS, preset.isCleanUpUpgradeExternalLinks()); + storage.put(CLEANUP_HTML, preset.isConvertHTMLToLatex()); + storage.put(CLEANUP_CASE, preset.isConvertCase()); + storage.put(CLEANUP_LATEX, preset.isConvertLaTeX()); + storage.put(CLEANUP_UNITS, preset.isConvertUnits()); + storage.put(CLEANUP_UNICODE, preset.isConvertUnicodeToLatex()); + storage.put(CLEANUP_CONVERT_TO_BIBLATEX, preset.isConvertToBiblatex()); + storage.put(CLEANUP_FIX_FILE_LINKS, preset.isFixFileLinks()); + } } diff --git a/src/main/java/net/sf/jabref/gui/BasePanel.java b/src/main/java/net/sf/jabref/gui/BasePanel.java index f8eb36f930c..550275b92ae 100644 --- a/src/main/java/net/sf/jabref/gui/BasePanel.java +++ b/src/main/java/net/sf/jabref/gui/BasePanel.java @@ -38,7 +38,7 @@ import net.sf.jabref.groups.GroupTreeNode; import net.sf.jabref.gui.actions.Actions; import net.sf.jabref.gui.actions.BaseAction; -import net.sf.jabref.gui.actions.CleanUpAction; +import net.sf.jabref.gui.actions.CleanupAction; import net.sf.jabref.gui.desktop.JabRefDesktop; import net.sf.jabref.gui.entryeditor.EntryEditor; import net.sf.jabref.gui.fieldeditors.FieldEditor; @@ -294,7 +294,7 @@ public void output(String s) { private void setupActions() { SaveDatabaseAction saveAction = new SaveDatabaseAction(this); - CleanUpAction cleanUpAction = new CleanUpAction(this); + CleanupAction cleanUpAction = new CleanupAction(this, Globals.prefs); actions.put(Actions.UNDO, undoAction); actions.put(Actions.REDO, redoAction); diff --git a/src/main/java/net/sf/jabref/gui/CleanupPresetPanel.java b/src/main/java/net/sf/jabref/gui/CleanupPresetPanel.java new file mode 100644 index 00000000000..c02813e67f4 --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/CleanupPresetPanel.java @@ -0,0 +1,175 @@ +package net.sf.jabref.gui; + +import java.util.EnumSet; +import java.util.Objects; + +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import com.jgoodies.forms.builder.FormBuilder; +import com.jgoodies.forms.layout.FormLayout; + +import net.sf.jabref.Globals; +import net.sf.jabref.gui.preftabs.ImportSettingsTab; +import net.sf.jabref.logic.cleanup.CleanupPreset; +import net.sf.jabref.logic.l10n.Localization; + +public class CleanupPresetPanel { + + private JCheckBox cleanUpSuperscripts; + private JCheckBox cleanUpDOI; + private JCheckBox cleanUpMonth; + private JCheckBox cleanUpPageNumbers; + private JCheckBox cleanUpDate; + private JCheckBox cleanUpMakePathsRelative; + private JCheckBox cleanUpRenamePDF; + private JCheckBox cleanUpRenamePDFonlyRelativePaths; + private JCheckBox cleanUpUpgradeExternalLinks; + private JCheckBox cleanUpHTML; + private JCheckBox cleanUpCase; + private JCheckBox cleanUpLaTeX; + private JCheckBox cleanUpUnits; + private JCheckBox cleanUpUnicode; + private JCheckBox cleanUpBibLatex; + + private JPanel panel; + private CleanupPreset cleanupPreset; + + public CleanupPresetPanel(CleanupPreset cleanupPreset) { + this.cleanupPreset = Objects.requireNonNull(cleanupPreset); + + init(); + } + + private void init() { + cleanUpSuperscripts = new JCheckBox(Localization.lang("Convert 1st, 2nd, ... to real superscripts")); + cleanUpDOI = new JCheckBox( + Localization.lang("Move DOIs from note and URL field to DOI field and remove http prefix")); + cleanUpMonth = new JCheckBox(Localization.lang("Format content of month field to #mon#")); + cleanUpPageNumbers = new JCheckBox(Localization.lang("Ensure that page ranges are of the form num1--num2")); + cleanUpDate = new JCheckBox(Localization.lang("Format date field in the form yyyy-mm or yyyy-mm-dd")); + cleanUpMakePathsRelative = new JCheckBox( + Localization.lang("Make paths of linked files relative (if possible)")); + cleanUpRenamePDF = new JCheckBox(Localization.lang("Rename PDFs to given filename format pattern")); + cleanUpRenamePDF.addChangeListener( + event -> cleanUpRenamePDFonlyRelativePaths.setEnabled(cleanUpRenamePDF.isSelected())); + cleanUpRenamePDFonlyRelativePaths = new JCheckBox(Localization.lang("Rename only PDFs having a relative path")); + cleanUpUpgradeExternalLinks = new JCheckBox( + Localization.lang("Upgrade external PDF/PS links to use the '%0' field.", Globals.FILE_FIELD)); + cleanUpHTML = new JCheckBox(Localization.lang("Run HTML converter on title")); + cleanUpCase = new JCheckBox(Localization.lang("Run filter on title keeping the case of selected words")); + cleanUpLaTeX = new JCheckBox( + Localization.lang("Remove unneccessary $, {, and } and move adjacent numbers into equations")); + cleanUpUnits = new JCheckBox( + Localization.lang("Add brackets and replace separators with their non-breaking version for units")); + cleanUpUnicode = new JCheckBox(Localization.lang("Run Unicode converter on title, author(s), and abstract")); + cleanUpBibLatex = new JCheckBox(Localization + .lang("Convert to BibLatex format (for example, move the value of the 'journal' field to 'journaltitle')")); + updateDisplay(cleanupPreset); + + FormLayout layout = new FormLayout("left:15dlu,pref:grow", + "pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref"); + FormBuilder builder = FormBuilder.create().layout(layout); + builder.add(cleanUpHTML).xyw(1, 1, 2); + builder.add(cleanUpUnicode).xyw(1, 2, 2); + builder.add(cleanUpCase).xyw(1, 3, 2); + builder.add(cleanUpLaTeX).xyw(1, 4, 2); + builder.add(cleanUpUnits).xyw(1, 5, 2); + builder.add(cleanUpSuperscripts).xyw(1, 6, 2); + builder.add(cleanUpDOI).xyw(1, 7, 2); + builder.add(cleanUpMonth).xyw(1, 8, 2); + builder.add(cleanUpPageNumbers).xyw(1, 9, 2); + builder.add(cleanUpDate).xyw(1, 10, 2); + builder.add(cleanUpUpgradeExternalLinks).xyw(1, 11, 2); + builder.add(cleanUpMakePathsRelative).xyw(1, 12, 2); + builder.add(cleanUpRenamePDF).xyw(1, 13, 2); + String currentPattern = Localization.lang("Filename format pattern").concat(": ").concat( + Globals.prefs.get(ImportSettingsTab.PREF_IMPORT_FILENAMEPATTERN)); + builder.add(new JLabel(currentPattern)).xy(2, 14); + builder.add(cleanUpRenamePDFonlyRelativePaths).xy(2, 15); + builder.add(cleanUpBibLatex).xyw(1, 16, 2); + panel = builder.build(); + } + + private void updateDisplay(CleanupPreset preset) { + cleanUpSuperscripts.setSelected(preset.isCleanUpSuperscripts()); + cleanUpDOI.setSelected(preset.isCleanUpDOI()); + cleanUpMonth.setSelected(preset.isCleanUpMonth()); + cleanUpPageNumbers.setSelected(preset.isCleanUpPageNumbers()); + cleanUpDate.setSelected(preset.isCleanUpDate()); + cleanUpMakePathsRelative.setSelected(preset.isMakePathsRelative()); + cleanUpRenamePDF.setSelected(preset.isRenamePDF()); + cleanUpRenamePDFonlyRelativePaths.setSelected(preset.isRenamePdfOnlyRelativePaths()); + cleanUpRenamePDFonlyRelativePaths.setEnabled(cleanUpRenamePDF.isSelected()); + cleanUpUpgradeExternalLinks.setSelected(preset.isCleanUpUpgradeExternalLinks()); + cleanUpHTML.setSelected(preset.isConvertHTMLToLatex()); + cleanUpCase.setSelected(preset.isConvertCase()); + cleanUpLaTeX.setSelected(preset.isConvertLaTeX()); + cleanUpUnits.setSelected(preset.isConvertUnits()); + cleanUpUnicode.setSelected(preset.isConvertUnicodeToLatex()); + cleanUpBibLatex.setSelected(preset.isConvertToBiblatex()); + } + + public JPanel getPanel() { + return panel; + } + + public CleanupPreset getCleanupPreset() { + + EnumSet activeJobs = EnumSet.noneOf(CleanupPreset.CleanupStep.class); + + if (cleanUpSuperscripts.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_SUPERSCRIPTS); + } + if (cleanUpDOI.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_DOI); + } + if (cleanUpMonth.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_MONTH); + } + if (cleanUpPageNumbers.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_PAGE_NUMBERS); + } + if (cleanUpDate.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_DATE); + } + if (cleanUpMakePathsRelative.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.MAKE_PATHS_RELATIVE); + } + if (cleanUpRenamePDF.isSelected()) { + if (cleanUpRenamePDFonlyRelativePaths.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS); + } else { + activeJobs.add(CleanupPreset.CleanupStep.RENAME_PDF); + } + } + + if (cleanUpUpgradeExternalLinks.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); + } + if (cleanUpHTML.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CONVERT_HTML_TO_LATEX); + } + if (cleanUpCase.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CONVERT_CASE); + } + if (cleanUpLaTeX.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CONVERT_LATEX); + } + if (cleanUpUnits.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CONVERT_UNITS); + } + if (cleanUpUnicode.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CONVERT_UNICODE_TO_LATEX); + } + if (cleanUpBibLatex.isSelected()) { + activeJobs.add(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX); + } + + activeJobs.add(CleanupPreset.CleanupStep.FIX_FILE_LINKS); + + cleanupPreset = new CleanupPreset(activeJobs); + return cleanupPreset; + } +} diff --git a/src/main/java/net/sf/jabref/gui/FileListEntry.java b/src/main/java/net/sf/jabref/gui/FileListEntry.java index db4e817c128..e7bc87b9019 100644 --- a/src/main/java/net/sf/jabref/gui/FileListEntry.java +++ b/src/main/java/net/sf/jabref/gui/FileListEntry.java @@ -50,8 +50,4 @@ private String getTypeName() { public String toString() { return description + " : " + link + " : " + type; } - - public FileListEntry switchLinkAndDescription() { - return new FileListEntry(link, description, type); - } } diff --git a/src/main/java/net/sf/jabref/gui/actions/CleanUpAction.java b/src/main/java/net/sf/jabref/gui/actions/CleanUpAction.java deleted file mode 100644 index fca939025aa..00000000000 --- a/src/main/java/net/sf/jabref/gui/actions/CleanUpAction.java +++ /dev/null @@ -1,466 +0,0 @@ -/* Copyright (C) 2012-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.gui.actions; - -import java.util.List; -import java.util.Map; - -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import net.sf.jabref.*; -import net.sf.jabref.gui.*; -import net.sf.jabref.gui.preftabs.ImportSettingsTab; -import net.sf.jabref.gui.worker.AbstractWorker; -import net.sf.jabref.gui.undo.NamedCompound; -import net.sf.jabref.gui.undo.UndoableFieldChange; - -import com.jgoodies.forms.builder.FormBuilder; -import com.jgoodies.forms.layout.FormLayout; - -import net.sf.jabref.logic.FieldChange; -import net.sf.jabref.logic.cleanup.Cleaner; -import net.sf.jabref.logic.cleanup.DoiCleanup; -import net.sf.jabref.logic.cleanup.FieldFormatterCleanup; -import net.sf.jabref.logic.cleanup.FormatterCleanup; -import net.sf.jabref.logic.formatter.BibtexFieldFormatters; -import net.sf.jabref.logic.l10n.Localization; -import net.sf.jabref.model.database.BibDatabase; -import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.util.Util; - -public class CleanUpAction extends AbstractWorker { - - private static final String AKS_AUTO_NAMING_PDFS_AGAIN = "AskAutoNamingPDFsAgain"; - private static final String CLEANUP_DOI = "CleanUpDOI"; - private static final String CLEANUP_MONTH = "CleanUpMonth"; - private static final String CLEANUP_PAGENUMBERS = "CleanUpPageNumbers"; - private static final String CLEANUP_DATE = "CleanUpDate"; - private static final String CLEANUP_MAKEPATHSRELATIVE = "CleanUpMakePathsRelative"; - private static final String CLEANUP_RENAMEPDF = "CleanUpRenamePDF"; - private static final String CLEANUP_RENAMEPDF_ONLYRELATIVE_PATHS = "CleanUpRenamePDFonlyRelativePaths"; - private static final String CLEANUP_UPGRADE_EXTERNAL_LINKS = "CleanUpUpgradeExternalLinks"; - private static final String CLEANUP_SUPERSCRIPTS = "CleanUpSuperscripts"; - private static final String CLEANUP_HTML = "CleanUpHTML"; - private static final String CLEANUP_CASE = "CleanUpCase"; - private static final String CLEANUP_LATEX = "CleanUpLaTeX"; - private static final String CLEANUP_UNITS = "CleanUpUnits"; - private static final String CLEANUP_UNICODE = "CleanUpUnicode"; - private static final String CLEANUP_CONVERTTOBIBLATEX = "CleanUpConvertToBiblatex"; - - - public static void putDefaults(Map defaults) { - defaults.put(AKS_AUTO_NAMING_PDFS_AGAIN, Boolean.TRUE); - defaults.put(CLEANUP_SUPERSCRIPTS, Boolean.TRUE); - defaults.put(CLEANUP_DOI, Boolean.TRUE); - defaults.put(CLEANUP_MONTH, Boolean.TRUE); - defaults.put(CLEANUP_PAGENUMBERS, Boolean.TRUE); - defaults.put(CLEANUP_DATE, Boolean.TRUE); - defaults.put(CLEANUP_MAKEPATHSRELATIVE, Boolean.TRUE); - defaults.put(CLEANUP_RENAMEPDF, Boolean.TRUE); - defaults.put(CLEANUP_RENAMEPDF_ONLYRELATIVE_PATHS, Boolean.FALSE); - defaults.put(CLEANUP_UPGRADE_EXTERNAL_LINKS, Boolean.FALSE); - defaults.put(CLEANUP_MAKEPATHSRELATIVE, Boolean.TRUE); - defaults.put(CLEANUP_HTML, Boolean.TRUE); - defaults.put(CLEANUP_CASE, Boolean.TRUE); - defaults.put(CLEANUP_LATEX, Boolean.TRUE); - defaults.put(CLEANUP_UNITS, Boolean.TRUE); - defaults.put(CLEANUP_UNICODE, Boolean.TRUE); - defaults.put(CLEANUP_CONVERTTOBIBLATEX, Boolean.FALSE); - } - - private JCheckBox cleanUpSuperscripts; - private JCheckBox cleanUpDOI; - private JCheckBox cleanUpMonth; - private JCheckBox cleanUpPageNumbers; - private JCheckBox cleanUpDate; - private JCheckBox cleanUpMakePathsRelative; - private JCheckBox cleanUpRenamePDF; - private JCheckBox cleanUpRenamePDFonlyRelativePaths; - private JCheckBox cleanUpUpgradeExternalLinks; - private JCheckBox cleanUpHTML; - private JCheckBox cleanUpCase; - private JCheckBox cleanUpLaTeX; - private JCheckBox cleanUpUnits; - private JCheckBox cleanUpUnicode; - private JCheckBox cleanUpBibLatex; - - private JPanel optionsPanel = new JPanel(); - private final BasePanel panel; - private final JabRefFrame frame; - - /** - * Global variable to count unsuccessful renames - */ - private int unsuccessfulRenames; - - private boolean cancelled; - private int modifiedEntriesCount; - - - public CleanUpAction(BasePanel panel) { - this.panel = panel; - this.frame = panel.frame(); - initOptionsPanel(); - } - - private void initOptionsPanel() { - cleanUpSuperscripts = new JCheckBox(Localization.lang("Convert 1st, 2nd, ... to real superscripts")); - cleanUpDOI = new JCheckBox(Localization.lang("Move DOIs from note and URL field to DOI field and remove http prefix")); - cleanUpMonth = new JCheckBox(Localization.lang("Format content of month field to #mon#")); - cleanUpPageNumbers = new JCheckBox(Localization.lang("Ensure that page ranges are of the form num1--num2")); - cleanUpDate = new JCheckBox(Localization.lang("Format date field in the form yyyy-mm or yyyy-mm-dd")); - cleanUpMakePathsRelative = new JCheckBox(Localization.lang("Make paths of linked files relative (if possible)")); - cleanUpRenamePDF = new JCheckBox(Localization.lang("Rename PDFs to given filename format pattern")); - cleanUpRenamePDF.addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent arg0) { - cleanUpRenamePDFonlyRelativePaths.setEnabled(cleanUpRenamePDF.isSelected()); - } - }); - cleanUpRenamePDFonlyRelativePaths = new JCheckBox(Localization.lang("Rename only PDFs having a relative path")); - cleanUpUpgradeExternalLinks = new JCheckBox(Localization.lang("Upgrade external PDF/PS links to use the '%0' field.", Globals.FILE_FIELD)); - cleanUpHTML = new JCheckBox(Localization.lang("Run HTML converter on title")); - cleanUpCase = new JCheckBox(Localization.lang("Run filter on title keeping the case of selected words")); - cleanUpLaTeX = new JCheckBox(Localization.lang("Remove unneccessary $, {, and } and move adjacent numbers into equations")); - cleanUpUnits = new JCheckBox(Localization.lang("Add brackets and replace separators with their non-breaking version for units")); - cleanUpUnicode = new JCheckBox(Localization.lang("Run Unicode converter on title, author(s), and abstract")); - cleanUpBibLatex = new JCheckBox(Localization.lang("Convert to BibLatex format (for example, move the value of the 'journal' field to 'journaltitle')")); - retrieveSettings(); - - FormLayout layout = new FormLayout("left:15dlu,pref:grow", - "pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref"); - FormBuilder builder = FormBuilder.create().layout(layout); - builder.add(cleanUpHTML).xyw(1, 1, 2); - builder.add(cleanUpUnicode).xyw(1, 2, 2); - builder.add(cleanUpCase).xyw(1, 3, 2); - builder.add(cleanUpLaTeX).xyw(1, 4, 2); - builder.add(cleanUpUnits).xyw(1, 5, 2); - builder.add(cleanUpSuperscripts).xyw(1, 6, 2); - builder.add(cleanUpDOI).xyw(1, 7, 2); - builder.add(cleanUpMonth).xyw(1, 8, 2); - builder.add(cleanUpPageNumbers).xyw(1, 9, 2); - builder.add(cleanUpDate).xyw(1, 10, 2); - builder.add(cleanUpUpgradeExternalLinks).xyw(1, 11, 2); - builder.add(cleanUpMakePathsRelative).xyw(1, 12, 2); - builder.add(cleanUpRenamePDF).xyw(1, 13, 2); - String currentPattern = Localization.lang("Filename format pattern").concat(": ").concat(Globals.prefs.get(ImportSettingsTab.PREF_IMPORT_FILENAMEPATTERN)); - builder.add(new JLabel(currentPattern)).xy(2, 14); - builder.add(cleanUpRenamePDFonlyRelativePaths).xy(2, 15); - builder.add(cleanUpBibLatex).xyw(1, 16, 2); - optionsPanel = builder.build(); - - } - - private void retrieveSettings() { - cleanUpSuperscripts.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_SUPERSCRIPTS)); - cleanUpDOI.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_DOI)); - cleanUpMonth.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_MONTH)); - cleanUpPageNumbers.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_PAGENUMBERS)); - cleanUpDate.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_DATE)); - cleanUpMakePathsRelative.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_MAKEPATHSRELATIVE)); - cleanUpRenamePDF.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_RENAMEPDF)); - cleanUpRenamePDFonlyRelativePaths.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_RENAMEPDF_ONLYRELATIVE_PATHS)); - cleanUpRenamePDFonlyRelativePaths.setEnabled(cleanUpRenamePDF.isSelected()); - cleanUpUpgradeExternalLinks.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_UPGRADE_EXTERNAL_LINKS)); - cleanUpHTML.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_HTML)); - cleanUpCase.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_CASE)); - cleanUpLaTeX.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_LATEX)); - cleanUpUnits.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_UNITS)); - cleanUpUnicode.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_UNICODE)); - cleanUpBibLatex.setSelected(Globals.prefs.getBoolean(CleanUpAction.CLEANUP_CONVERTTOBIBLATEX)); - } - - private void storeSettings() { - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_SUPERSCRIPTS, cleanUpSuperscripts.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_DOI, cleanUpDOI.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_MONTH, cleanUpMonth.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_PAGENUMBERS, cleanUpPageNumbers.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_DATE, cleanUpDate.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_MAKEPATHSRELATIVE, cleanUpMakePathsRelative.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_RENAMEPDF, cleanUpRenamePDF.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_RENAMEPDF_ONLYRELATIVE_PATHS, cleanUpRenamePDFonlyRelativePaths.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_UPGRADE_EXTERNAL_LINKS, cleanUpUpgradeExternalLinks.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_HTML, cleanUpHTML.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_CASE, cleanUpCase.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_LATEX, cleanUpLaTeX.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_UNITS, cleanUpUnits.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_UNICODE, cleanUpUnicode.isSelected()); - Globals.prefs.putBoolean(CleanUpAction.CLEANUP_CONVERTTOBIBLATEX, cleanUpBibLatex.isSelected()); - } - - private int showCleanUpDialog() { - String dialogTitle = Localization.lang("Cleanup entries"); - - Object[] messages = {Localization.lang("What would you like to clean up?"), optionsPanel}; - return JOptionPane.showConfirmDialog(frame, messages, dialogTitle, - JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); - } - - @Override - public void init() { - cancelled = false; - modifiedEntriesCount = 0; - int numSelected = panel.getSelectedEntries().length; - if (numSelected == 0) { // None selected. Inform the user to select entries first. - JOptionPane.showMessageDialog(frame, Localization.lang("First select entries to clean up."), - Localization.lang("Cleanup entry"), JOptionPane.INFORMATION_MESSAGE); - cancelled = true; - return; - } - frame.block(); - panel.output(Localization.lang("Doing a cleanup for %0 entries...", Integer.toString(numSelected))); - } - - @Override - public void run() { - if (cancelled) { - return; - } - int choice = showCleanUpDialog(); - if (choice != JOptionPane.OK_OPTION) { - cancelled = true; - return; - } - storeSettings(); - boolean choiceCleanUpSuperscripts = cleanUpSuperscripts.isSelected(); - boolean choiceCleanUpDOI = cleanUpDOI.isSelected(); - boolean choiceCleanUpMonth = cleanUpMonth.isSelected(); - boolean choiceCleanUpPageNumbers = cleanUpPageNumbers.isSelected(); - boolean choiceCleanUpDate = cleanUpDate.isSelected(); - boolean choiceCleanUpUpgradeExternalLinks = cleanUpUpgradeExternalLinks.isSelected(); - boolean choiceMakePathsRelative = cleanUpMakePathsRelative.isSelected(); - boolean choiceRenamePDF = cleanUpRenamePDF.isSelected(); - boolean choiceConvertHTML = cleanUpHTML.isSelected(); - boolean choiceConvertCase = cleanUpCase.isSelected(); - boolean choiceConvertLaTeX = cleanUpLaTeX.isSelected(); - boolean choiceConvertUnits = cleanUpUnits.isSelected(); - boolean choiceConvertUnicode = cleanUpUnicode.isSelected(); - boolean choiceConvertToBiblatex = cleanUpBibLatex.isSelected(); - - if (choiceRenamePDF && Globals.prefs.getBoolean(CleanUpAction.AKS_AUTO_NAMING_PDFS_AGAIN)) { - CheckBoxMessage cbm = new CheckBoxMessage(Localization.lang("Auto-generating PDF-Names does not support undo. Continue?"), - Localization.lang("Disable this confirmation dialog"), false); - int answer = JOptionPane.showConfirmDialog(frame, cbm, Localization.lang("Autogenerate PDF Names"), - JOptionPane.YES_NO_OPTION); - if (cbm.isSelected()) { - Globals.prefs.putBoolean(CleanUpAction.AKS_AUTO_NAMING_PDFS_AGAIN, false); - } - if (answer == JOptionPane.NO_OPTION) { - cancelled = true; - return; - } - } - - for (BibEntry entry : panel.getSelectedEntries()) { - // undo granularity is on entry level - NamedCompound ce = new NamedCompound(Localization.lang("Cleanup entry")); - - if (choiceCleanUpUpgradeExternalLinks) { - doUpgradePdfPsToFile(entry, ce); - } - if (choiceCleanUpSuperscripts) { - doCleanUpSuperscripts(entry, ce); - } - if (choiceCleanUpDOI) { - doCleanUpDOI(entry, ce); - } - if (choiceCleanUpMonth) { - doCleanUpMonth(entry, ce); - } - if (choiceCleanUpPageNumbers) { - doCleanUpPageNumbers(entry, ce); - } - if (choiceCleanUpDate) { - doCleanUpDate(entry, ce); - } - - fixWrongFileEntries(entry, ce); - if (choiceMakePathsRelative) { - doMakePathsRelative(entry, ce); - } - if (choiceRenamePDF) { - doRenamePDFs(entry, ce); - } - if (choiceConvertHTML) { - doConvertHTML(entry, ce); - } - if (choiceConvertUnits) { - doConvertUnits(entry, ce); - } - if (choiceConvertCase) { - doConvertCase(entry, ce); - } - if (choiceConvertLaTeX) { - doConvertLaTeX(entry, ce); - } - if (choiceConvertUnicode) { - doConvertUnicode(entry, ce); - } - if (choiceConvertToBiblatex) { - doConvertToBiblatex(entry, ce); - } - - ce.end(); - if (ce.hasEdits()) { - modifiedEntriesCount++; - panel.undoManager.addEdit(ce); - } - } - } - - @Override - public void update() { - if (cancelled) { - frame.unblock(); - return; - } - if (unsuccessfulRenames > 0) { //Rename failed for at least one entry - JOptionPane.showMessageDialog(frame, - Localization.lang("File rename failed for %0 entries.", Integer.toString(unsuccessfulRenames)), - Localization.lang("Autogenerate PDF Names"), JOptionPane.INFORMATION_MESSAGE); - } - if (modifiedEntriesCount > 0) { - panel.updateEntryEditorIfShowing(); - panel.markBaseChanged(); - } - String message; - switch (modifiedEntriesCount) { - case 0: - message = Localization.lang("No entry needed a clean up"); - break; - case 1: - message = Localization.lang("One entry needed a clean up"); - break; - default: - message = Localization.lang("%0 entries needed a clean up", Integer.toString(modifiedEntriesCount)); - break; - } - panel.output(message); - frame.unblock(); - } - - /** - * Collects file links from the pdf or ps field, and adds them to the list contained in the file field. - */ - private void doUpgradePdfPsToFile(BibEntry entry, NamedCompound ce) { - Util.upgradePdfPsToFile(entry, new String[] {"pdf", "ps"}, ce); - } - - /** - * Converts the text in 1st, 2nd, ... to real superscripts by wrapping in \textsuperscript{st}, ... - */ - private static void doCleanUpSuperscripts(BibEntry entry, NamedCompound ce) { - doCleanup(new FormatterCleanup(BibtexFieldFormatters.SUPERSCRIPTS), entry, ce); - } - - /** - * Removes the http://... for each DOI. Moves DOIs from URL and NOTE filed to DOI field. - */ - private static void doCleanUpDOI(BibEntry entry, NamedCompound ce) { - doCleanup(new DoiCleanup(), entry, ce); - } - - private static void doCleanUpMonth(BibEntry entry, NamedCompound ce) { - doCleanup(FieldFormatterCleanup.MONTH, entry, ce); - } - - private static void doCleanUpPageNumbers(BibEntry entry, NamedCompound ce) { - doCleanup(FieldFormatterCleanup.PAGE_NUMBERS, entry, ce); - } - - private static void fixWrongFileEntries(BibEntry entry, NamedCompound ce) { - doCleanup(new FileEntryCleaner(), entry, ce); - } - - private void doMakePathsRelative(BibEntry entry, NamedCompound ce) { - doCleanup(new RelativePathsCleanup(panel.metaData().getFileDirectory(Globals.FILE_FIELD)), entry, ce); - } - - private void doRenamePDFs(BibEntry entry, NamedCompound ce) { - List paths = panel.metaData().getFileDirectory(Globals.FILE_FIELD); - BibDatabase database = panel.database(); - Boolean onlyRelativePaths = cleanUpRenamePDFonlyRelativePaths.isSelected(); - RenamePdfCleanup cleaner = new RenamePdfCleanup(paths, onlyRelativePaths, database); - doCleanup(cleaner, entry, ce); - unsuccessfulRenames += cleaner.getUnsuccessfulRenames(); - } - - /** - * Converts HTML code to LaTeX code - */ - private static void doConvertHTML(BibEntry entry, NamedCompound ce) { - doCleanup(FieldFormatterCleanup.TITLE_HTML, entry, ce); - } - - /** - * Converts Unicode characters to LaTeX code - */ - private static void doConvertUnicode(BibEntry entry, NamedCompound ce) { - doCleanup(new UnicodeCleanup(), entry, ce); - } - - /** - * Adds curly brackets {} around keywords - */ - private static void doConvertCase(BibEntry entry, NamedCompound ce) { - doCleanup(FieldFormatterCleanup.TITLE_CASE, entry, ce); - } - - private static void doConvertUnits(BibEntry entry, NamedCompound ce) { - doCleanup(FieldFormatterCleanup.TITLE_UNITS, entry, ce); - } - - private static void doConvertLaTeX(BibEntry entry, NamedCompound ce) { - doCleanup(FieldFormatterCleanup.TITLE_LATEX, entry, ce); - } - - /** - * Converts to BibLatex format - */ - private static void doConvertToBiblatex(BibEntry entry, NamedCompound ce) { - doCleanup(new BiblatexCleanup(), entry, ce); - } - - /** - * Format dates correctly (yyyy-mm-dd or yyyy-mm) - */ - private static void doCleanUpDate(BibEntry entry, NamedCompound ce) { - doCleanup(FieldFormatterCleanup.DATES, entry, ce); - } - - /** - * Runs the field formatter on the entry and records the change. - */ - private static void doCleanup(Cleaner cleaner, BibEntry entry, NamedCompound ce) { - // Run cleaner - List changes = cleaner.cleanup(entry); - - if (changes.isEmpty()) { - return; - } - - // Register undo action - for (FieldChange change : changes) { - ce.addEdit(new UndoableFieldChange(change)); - } - } -} diff --git a/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java new file mode 100644 index 00000000000..f4e85073562 --- /dev/null +++ b/src/main/java/net/sf/jabref/gui/actions/CleanupAction.java @@ -0,0 +1,174 @@ +/* Copyright (C) 2012-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.gui.actions; + +import net.sf.jabref.Globals; +import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.gui.BasePanel; +import net.sf.jabref.gui.CheckBoxMessage; +import net.sf.jabref.gui.CleanupPresetPanel; +import net.sf.jabref.gui.JabRefFrame; +import net.sf.jabref.gui.undo.NamedCompound; +import net.sf.jabref.gui.undo.UndoableFieldChange; +import net.sf.jabref.gui.worker.AbstractWorker; +import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.logic.cleanup.CleanupPreset; +import net.sf.jabref.logic.cleanup.CleanupWorker; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.BibEntry; + +import javax.swing.*; +import java.util.List; +import java.util.Objects; + +public class CleanupAction extends AbstractWorker { + + private final BasePanel panel; + private final JabRefFrame frame; + + /** + * Global variable to count unsuccessful renames + */ + private int unsuccessfulRenames; + + private boolean cancelled; + private int modifiedEntriesCount; + private final JabRefPreferences preferences; + private final CleanupPresetPanel presetPanel; + + public CleanupAction(BasePanel panel, JabRefPreferences preferences) { + this.panel = panel; + this.frame = panel.frame(); + this.preferences = Objects.requireNonNull(preferences); + this.presetPanel = new CleanupPresetPanel(CleanupPreset.loadFromPreferences(preferences)); + } + + @Override + public void init() { + cancelled = false; + modifiedEntriesCount = 0; + int numSelected = panel.getSelectedEntries().length; + if (numSelected == 0) { // None selected. Inform the user to select entries first. + JOptionPane.showMessageDialog(frame, Localization.lang("First select entries to clean up."), + Localization.lang("Cleanup entry"), JOptionPane.INFORMATION_MESSAGE); + cancelled = true; + return; + } + frame.block(); + panel.output(Localization.lang("Doing a cleanup for %0 entries...", Integer.toString(numSelected))); + } + + @Override + public void run() { + if (cancelled) { + return; + } + int choice = showDialog(); + if (choice != JOptionPane.OK_OPTION) { + cancelled = true; + return; + } + CleanupPreset cleanupPreset = presetPanel.getCleanupPreset(); + cleanupPreset.storeInPreferences(preferences); + + if (cleanupPreset.isRenamePDF() && Globals.prefs.getBoolean(JabRefPreferences.AKS_AUTO_NAMING_PDFS_AGAIN)) { + CheckBoxMessage cbm = new CheckBoxMessage( + Localization.lang("Auto-generating PDF-Names does not support undo. Continue?"), + Localization.lang("Disable this confirmation dialog"), false); + int answer = JOptionPane.showConfirmDialog(frame, cbm, Localization.lang("Autogenerate PDF Names"), + JOptionPane.YES_NO_OPTION); + if (cbm.isSelected()) { + Globals.prefs.putBoolean(JabRefPreferences.AKS_AUTO_NAMING_PDFS_AGAIN, false); + } + if (answer == JOptionPane.NO_OPTION) { + cancelled = true; + return; + } + } + + for (BibEntry entry : panel.getSelectedEntries()) { + // undo granularity is on entry level + NamedCompound ce = new NamedCompound(Localization.lang("Cleanup entry")); + + doCleanup(cleanupPreset, entry, ce); + + ce.end(); + if (ce.hasEdits()) { + modifiedEntriesCount++; + panel.undoManager.addEdit(ce); + } + } + } + + @Override + public void update() { + if (cancelled) { + frame.unblock(); + return; + } + if (unsuccessfulRenames > 0) { //Rename failed for at least one entry + JOptionPane.showMessageDialog(frame, + Localization.lang("File rename failed for %0 entries.", Integer.toString(unsuccessfulRenames)), + Localization.lang("Autogenerate PDF Names"), JOptionPane.INFORMATION_MESSAGE); + } + if (modifiedEntriesCount > 0) { + panel.updateEntryEditorIfShowing(); + panel.markBaseChanged(); + } + String message; + switch (modifiedEntriesCount) { + case 0: + message = Localization.lang("No entry needed a clean up"); + break; + case 1: + message = Localization.lang("One entry needed a clean up"); + break; + default: + message = Localization.lang("%0 entries needed a clean up", Integer.toString(modifiedEntriesCount)); + break; + } + panel.output(message); + frame.unblock(); + } + + private int showDialog() { + String dialogTitle = Localization.lang("Cleanup entries"); + + Object[] messages = {Localization.lang("What would you like to clean up?"), presetPanel.getPanel()}; + return JOptionPane.showConfirmDialog(frame, messages, dialogTitle, JOptionPane.OK_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE); + } + + /** + * Runs the cleanup on the entry and records the change. + */ + private void doCleanup(CleanupPreset preset, BibEntry entry, NamedCompound ce) { + // Run cleaner + CleanupWorker cleaner = new CleanupWorker(preset, panel.metaData().getFileDirectory(Globals.FILE_FIELD)); + List changes = cleaner.cleanup(entry); + + unsuccessfulRenames = cleaner.getUnsuccessfulRenames(); + + if (changes.isEmpty()) { + return; + } + + // Register undo action + for (FieldChange change : changes) { + ce.addEdit(new UndoableFieldChange(change)); + } + } +} diff --git a/src/main/java/net/sf/jabref/gui/actions/FileEntryCleaner.java b/src/main/java/net/sf/jabref/gui/actions/FileEntryCleaner.java deleted file mode 100644 index 6bf42fdbc5e..00000000000 --- a/src/main/java/net/sf/jabref/gui/actions/FileEntryCleaner.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.sf.jabref.gui.actions; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import net.sf.jabref.Globals; -import net.sf.jabref.gui.FileListEntry; -import net.sf.jabref.gui.FileListTableModel; -import net.sf.jabref.logic.FieldChange; -import net.sf.jabref.logic.cleanup.Cleaner; -import net.sf.jabref.model.entry.BibEntry; - - -public class FileEntryCleaner implements Cleaner { - - @Override - public List cleanup(BibEntry entry) { - if (!entry.hasField(Globals.FILE_FIELD)) { - return new ArrayList<>(); - } - String oldValue = entry.getField(Globals.FILE_FIELD); - FileListTableModel flModel = new FileListTableModel(); - flModel.setContent(oldValue); - if (flModel.getRowCount() == 0) { - return new ArrayList<>(); - } - boolean changed = false; - for (int i = 0; i < flModel.getRowCount(); i++) { - FileListEntry flEntry = flModel.getEntry(i); - String link = flEntry.link; - String description = flEntry.description; - if ("".equals(link) && (!"".equals(description))) { - flModel.setEntry(i, flEntry.switchLinkAndDescription()); - - changed = true; - } - } - if (changed) { - String newValue = flModel.getStringRepresentation(); - assert(!oldValue.equals(newValue)); - entry.setField(Globals.FILE_FIELD, newValue); - FieldChange change = new FieldChange(entry, Globals.FILE_FIELD, oldValue, newValue); - return Collections.singletonList(change); - } - return new ArrayList<>(); - } - -} diff --git a/src/main/java/net/sf/jabref/gui/actions/RelativePathsCleanup.java b/src/main/java/net/sf/jabref/gui/actions/RelativePathsCleanup.java deleted file mode 100644 index 17fc03e1931..00000000000 --- a/src/main/java/net/sf/jabref/gui/actions/RelativePathsCleanup.java +++ /dev/null @@ -1,58 +0,0 @@ -package net.sf.jabref.gui.actions; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import net.sf.jabref.Globals; -import net.sf.jabref.gui.FileListEntry; -import net.sf.jabref.gui.FileListTableModel; -import net.sf.jabref.logic.FieldChange; -import net.sf.jabref.logic.cleanup.Cleaner; -import net.sf.jabref.logic.util.io.FileUtil; -import net.sf.jabref.model.entry.BibEntry; - - -public class RelativePathsCleanup implements Cleaner { - - private final List paths; - - public RelativePathsCleanup(List paths) { - this.paths = paths; - } - - @Override - public List cleanup(BibEntry entry) { - if (!entry.hasField(Globals.FILE_FIELD)) { - return new ArrayList<>(); - } - String oldValue = entry.getField(Globals.FILE_FIELD); - FileListTableModel flModel = new FileListTableModel(); - flModel.setContent(oldValue); - if (flModel.getRowCount() == 0) { - return new ArrayList<>(); - } - boolean changed = false; - for (int i = 0; i < flModel.getRowCount(); i++) { - FileListEntry flEntry = flModel.getEntry(i); - String oldFileName = flEntry.link; - String newFileName = FileUtil - .shortenFileName(new File(oldFileName), paths) - .toString(); - if (!oldFileName.equals(newFileName)) { - flModel.setEntry(i, new FileListEntry(flEntry.description, newFileName, flEntry.type)); - changed = true; - } - } - if (changed) { - String newValue = flModel.getStringRepresentation(); - assert(!oldValue.equals(newValue)); - entry.setField(Globals.FILE_FIELD, newValue); - FieldChange change = new FieldChange(entry, Globals.FILE_FIELD, oldValue, newValue); - return Collections.singletonList(change); - } - return new ArrayList<>(); - } - -} diff --git a/src/main/java/net/sf/jabref/logic/FieldChange.java b/src/main/java/net/sf/jabref/logic/FieldChange.java index b8af8e9f48b..ad7c52301c7 100644 --- a/src/main/java/net/sf/jabref/logic/FieldChange.java +++ b/src/main/java/net/sf/jabref/logic/FieldChange.java @@ -35,4 +35,65 @@ public String getOldValue() { public String getNewValue() { return this.newValue; } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + ((entry == null) ? 0 : entry.hashCode()); + result = (prime * result) + ((field == null) ? 0 : field.hashCode()); + result = (prime * result) + ((newValue == null) ? 0 : newValue.hashCode()); + result = (prime * result) + ((oldValue == null) ? 0 : oldValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + FieldChange other = (FieldChange) obj; + if (entry == null) { + if (other.entry != null) { + return false; + } + } else if (!entry.equals(other.entry)) { + return false; + } + if (field == null) { + if (other.field != null) { + return false; + } + } else if (!field.equals(other.field)) { + return false; + } + if (newValue == null) { + if (other.newValue != null) { + return false; + } + } else if (!newValue.equals(other.newValue)) { + return false; + } + if (oldValue == null) { + if (other.oldValue != null) { + return false; + } + } else if (!oldValue.equals(other.oldValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "FieldChange [entry=" + entry.getCiteKey() + ", field=" + field + ", oldValue=" + oldValue + + ", newValue=" + newValue + + "]"; + } } diff --git a/src/main/java/net/sf/jabref/gui/actions/BiblatexCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java similarity index 54% rename from src/main/java/net/sf/jabref/gui/actions/BiblatexCleanup.java rename to src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java index 2428e476aea..4bfd8d1f140 100644 --- a/src/main/java/net/sf/jabref/gui/actions/BiblatexCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/BiblatexCleanup.java @@ -1,18 +1,31 @@ -package net.sf.jabref.gui.actions; +/* 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.logic.cleanup; import java.util.ArrayList; import java.util.List; import java.util.Map; import net.sf.jabref.logic.FieldChange; -import net.sf.jabref.logic.cleanup.Cleaner; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.model.entry.EntryConverter; /** * Converts the entry to BibLatex format. */ -public class BiblatexCleanup implements Cleaner { +public class BiblatexCleanup implements CleanupJob { @Override public List cleanup(BibEntry entry) { @@ -37,13 +50,16 @@ public List cleanup(BibEntry entry) { String newDate = entry.getFieldOrAlias("date"); String oldYear = entry.getField("year"); String oldMonth = entry.getField("month"); - entry.setField("date", newDate); - entry.clearField("year"); - entry.clearField("month"); - changes.add(new FieldChange(entry, "date", null, newDate)); - changes.add(new FieldChange(entry, "year", oldYear, null)); - changes.add(new FieldChange(entry, "month", oldMonth, null)); + if (newDate != null) { + entry.setField("date", newDate); + entry.clearField("year"); + entry.clearField("month"); + + changes.add(new FieldChange(entry, "date", null, newDate)); + changes.add(new FieldChange(entry, "year", oldYear, null)); + changes.add(new FieldChange(entry, "month", oldMonth, null)); + } } return changes; } diff --git a/src/main/java/net/sf/jabref/logic/cleanup/Cleaner.java b/src/main/java/net/sf/jabref/logic/cleanup/Cleaner.java deleted file mode 100644 index 21ca88a67c6..00000000000 --- a/src/main/java/net/sf/jabref/logic/cleanup/Cleaner.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.sf.jabref.logic.cleanup; - -import java.util.List; - -import net.sf.jabref.logic.FieldChange; -import net.sf.jabref.model.entry.BibEntry; - -public interface Cleaner { - - /** - * Cleanup the entry. - */ - List cleanup(BibEntry entry); - -} \ No newline at end of file diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupJob.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupJob.java new file mode 100644 index 00000000000..83cc7a3fdc3 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupJob.java @@ -0,0 +1,29 @@ +/* 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.logic.cleanup; + +import java.util.List; + +import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.entry.BibEntry; + +public interface CleanupJob { + + /** + * Cleanup the entry. + */ + List cleanup(BibEntry entry); + +} \ No newline at end of file diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java new file mode 100644 index 00000000000..bd458f7d3f0 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupPreset.java @@ -0,0 +1,221 @@ +/* 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.logic.cleanup; + +import net.sf.jabref.JabRefPreferences; + +import java.util.EnumSet; + +public class CleanupPreset { + + private final EnumSet activeJobs; + + public CleanupPreset(EnumSet activeJobs) { + this.activeJobs = activeJobs; + } + + public CleanupPreset(CleanupStep activeJob) { + this(EnumSet.of(activeJob)); + } + + public static CleanupPreset loadFromPreferences(JabRefPreferences preferences) { + + EnumSet activeJobs = EnumSet.noneOf(CleanupStep.class); + + if (preferences.getBoolean(JabRefPreferences.CLEANUP_SUPERSCRIPTS)) { + activeJobs.add(CleanupStep.CLEAN_UP_SUPERSCRIPTS); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_DOI)) { + activeJobs.add(CleanupStep.CLEAN_UP_DOI); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_MONTH)) { + activeJobs.add(CleanupStep.CLEAN_UP_MONTH); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_PAGE_NUMBERS)) { + activeJobs.add(CleanupStep.CLEAN_UP_PAGE_NUMBERS); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_DATE)) { + activeJobs.add(CleanupStep.CLEAN_UP_DATE); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_MAKE_PATHS_RELATIVE)) { + activeJobs.add(CleanupStep.MAKE_PATHS_RELATIVE); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_RENAME_PDF)) { + activeJobs.add(CleanupStep.RENAME_PDF); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS)) { + activeJobs.add(CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_UPGRADE_EXTERNAL_LINKS)) { + activeJobs.add(CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_HTML)) { + activeJobs.add(CleanupStep.CONVERT_HTML_TO_LATEX); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_CASE)) { + activeJobs.add(CleanupStep.CONVERT_CASE); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_LATEX)) { + activeJobs.add(CleanupStep.CONVERT_LATEX); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_UNITS)) { + activeJobs.add(CleanupStep.CONVERT_UNITS); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_UNICODE)) { + activeJobs.add(CleanupStep.CONVERT_UNICODE_TO_LATEX); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBLATEX)) { + activeJobs.add(CleanupStep.CONVERT_TO_BIBLATEX); + } + if (preferences.getBoolean(JabRefPreferences.CLEANUP_FIX_FILE_LINKS)) { + activeJobs.add(CleanupStep.FIX_FILE_LINKS); + } + + return new CleanupPreset(activeJobs); + } + + public boolean isCleanUpUpgradeExternalLinks() { + return isActive(CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); + } + + public boolean isCleanUpSuperscripts() { + return isActive(CleanupStep.CLEAN_UP_SUPERSCRIPTS); + } + + public boolean isCleanUpDOI() { + return isActive(CleanupStep.CLEAN_UP_DOI); + } + + public boolean isCleanUpMonth() { + return isActive(CleanupStep.CLEAN_UP_MONTH); + } + + public boolean isCleanUpPageNumbers() { + return isActive(CleanupStep.CLEAN_UP_PAGE_NUMBERS); + } + + public boolean isCleanUpDate() { + return isActive(CleanupStep.CLEAN_UP_DATE); + } + + public boolean isFixFileLinks() { + return isActive(CleanupStep.FIX_FILE_LINKS); + } + + public boolean isMakePathsRelative() { + return isActive(CleanupStep.MAKE_PATHS_RELATIVE); + } + + public boolean isRenamePDF() { + return isActive(CleanupStep.RENAME_PDF) || isActive(CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS); + } + + public boolean isConvertHTMLToLatex() { + return isActive(CleanupStep.CONVERT_HTML_TO_LATEX); + } + + public boolean isConvertUnits() { + return isActive(CleanupStep.CONVERT_UNITS); + } + + public boolean isConvertCase() { + return isActive(CleanupStep.CONVERT_CASE); + } + + public boolean isConvertLaTeX() { + return isActive(CleanupStep.CONVERT_LATEX); + } + + public boolean isConvertUnicodeToLatex() { + return isActive(CleanupStep.CONVERT_UNICODE_TO_LATEX); + } + + public boolean isConvertToBiblatex() { + return isActive(CleanupStep.CONVERT_TO_BIBLATEX); + } + + public boolean isRenamePdfOnlyRelativePaths() { + return isActive(CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS); + } + + public void storeInPreferences(JabRefPreferences preferences) { + + preferences.putBoolean(JabRefPreferences.CLEANUP_SUPERSCRIPTS, isActive(CleanupStep.CLEAN_UP_SUPERSCRIPTS)); + preferences.putBoolean(JabRefPreferences.CLEANUP_DOI, isActive(CleanupStep.CLEAN_UP_DOI)); + preferences.putBoolean(JabRefPreferences.CLEANUP_MONTH, isActive(CleanupStep.CLEAN_UP_MONTH)); + preferences.putBoolean(JabRefPreferences.CLEANUP_PAGE_NUMBERS, isActive(CleanupStep.CLEAN_UP_PAGE_NUMBERS)); + preferences.putBoolean(JabRefPreferences.CLEANUP_DATE, isActive(CleanupStep.CLEAN_UP_DATE)); + preferences.putBoolean(JabRefPreferences.CLEANUP_MAKE_PATHS_RELATIVE, isActive(CleanupStep.MAKE_PATHS_RELATIVE)); + preferences.putBoolean(JabRefPreferences.CLEANUP_RENAME_PDF, isActive(CleanupStep.RENAME_PDF)); + preferences.putBoolean(JabRefPreferences.CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS, + isActive(CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS)); + preferences.putBoolean(JabRefPreferences.CLEANUP_UPGRADE_EXTERNAL_LINKS, + isActive(CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS)); + preferences.putBoolean(JabRefPreferences.CLEANUP_HTML, isActive(CleanupStep.CONVERT_HTML_TO_LATEX)); + preferences.putBoolean(JabRefPreferences.CLEANUP_CASE, isActive(CleanupStep.CONVERT_CASE)); + preferences.putBoolean(JabRefPreferences.CLEANUP_LATEX, isActive(CleanupStep.CONVERT_LATEX)); + preferences.putBoolean(JabRefPreferences.CLEANUP_UNITS, isActive(CleanupStep.CONVERT_UNITS)); + preferences.putBoolean(JabRefPreferences.CLEANUP_UNICODE, isActive(CleanupStep.CONVERT_UNICODE_TO_LATEX)); + preferences.putBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBLATEX, isActive(CleanupStep.CONVERT_TO_BIBLATEX)); + preferences.putBoolean(JabRefPreferences.CLEANUP_FIX_FILE_LINKS, isActive(CleanupStep.FIX_FILE_LINKS)); + } + + private Boolean isActive(CleanupStep step) { + return activeJobs.contains(step); + } + + public enum CleanupStep { + /** + * Converts the text in 1st, 2nd, ... to real superscripts by wrapping in \textsuperscript{st}, ... + */ + CLEAN_UP_SUPERSCRIPTS, + /** + * Removes the http://... for each DOI. Moves DOIs from URL and NOTE filed to DOI field. + */ + CLEAN_UP_DOI, + CLEAN_UP_MONTH, + CLEAN_UP_PAGE_NUMBERS, + /** + * Format dates correctly (yyyy-mm-dd or yyyy-mm) + */ + CLEAN_UP_DATE, + MAKE_PATHS_RELATIVE, + RENAME_PDF, + RENAME_PDF_ONLY_RELATIVE_PATHS, + /** + * Collects file links from the pdf or ps field, and adds them to the list contained in the file field. + */ + CLEAN_UP_UPGRADE_EXTERNAL_LINKS, + /** + * Converts HTML code to LaTeX code + */ + CONVERT_HTML_TO_LATEX, + /** + * Adds curly brackets {} around keywords + */ + CONVERT_CASE, + CONVERT_LATEX, + CONVERT_UNITS, + /** + * Converts Unicode characters to LaTeX code + */ + CONVERT_UNICODE_TO_LATEX, + /** + * Converts to BibLatex format + */ + CONVERT_TO_BIBLATEX, + FIX_FILE_LINKS + } +} diff --git a/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java new file mode 100644 index 00000000000..54492d1271e --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/cleanup/CleanupWorker.java @@ -0,0 +1,118 @@ +/* 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.logic.cleanup; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.logic.formatter.BibtexFieldFormatters; +import net.sf.jabref.model.database.BibDatabase; +import net.sf.jabref.model.entry.BibEntry; + +public class CleanupWorker { + + private final CleanupPreset preset; + private final List paths; + private final BibDatabase database; + private int unsuccessfulRenames; + + public CleanupWorker(CleanupPreset preset) { + this(preset, Collections.emptyList()); + } + + public CleanupWorker(CleanupPreset preset, List paths) { + this(preset, paths, null); + } + + public CleanupWorker(CleanupPreset preset, List paths, BibDatabase database) { + this.preset = Objects.requireNonNull(preset); + this.paths = Objects.requireNonNull(paths); + this.database = database; + } + + public int getUnsuccessfulRenames() { + return unsuccessfulRenames; + } + + public List cleanup(BibEntry entry) { + Objects.requireNonNull(entry); + + ArrayList jobs = determineCleanupActions(); + + ArrayList changes = new ArrayList<>(); + for (CleanupJob job : jobs) { + changes.addAll(job.cleanup(entry)); + } + + return changes; + } + + private ArrayList determineCleanupActions() { + ArrayList jobs = new ArrayList<>(); + + if (preset.isCleanUpUpgradeExternalLinks()) { + jobs.add(new UpgradePdfPsToFileCleanup(Arrays.asList("pdf", "ps"))); + } + if (preset.isCleanUpSuperscripts()) { + jobs.add(new FormatterCleanup(BibtexFieldFormatters.SUPERSCRIPTS)); + } + if (preset.isCleanUpDOI()) { + jobs.add(new DoiCleanup()); + } + if (preset.isCleanUpMonth()) { + jobs.add(FieldFormatterCleanup.MONTH); + } + if (preset.isCleanUpPageNumbers()) { + jobs.add(FieldFormatterCleanup.PAGE_NUMBERS); + } + if (preset.isCleanUpDate()) { + jobs.add(FieldFormatterCleanup.DATES); + } + if (preset.isFixFileLinks()) { + jobs.add(new FileLinksCleanup()); + } + if (preset.isMakePathsRelative()) { + jobs.add(new RelativePathsCleanup(paths)); + } + if (preset.isRenamePDF()) { + RenamePdfCleanup cleaner = new RenamePdfCleanup(paths, preset.isRenamePdfOnlyRelativePaths(), database); + jobs.add(cleaner); + unsuccessfulRenames += cleaner.getUnsuccessfulRenames(); + } + if (preset.isConvertHTMLToLatex()) { + jobs.add(FieldFormatterCleanup.TITLE_HTML); + } + if (preset.isConvertUnits()) { + jobs.add(FieldFormatterCleanup.TITLE_UNITS); + } + if (preset.isConvertCase()) { + jobs.add(FieldFormatterCleanup.TITLE_CASE); + } + if (preset.isConvertLaTeX()) { + jobs.add(FieldFormatterCleanup.TITLE_LATEX); + } + if (preset.isConvertUnicodeToLatex()) { + jobs.add(new UnicodeCleanup()); + } + if (preset.isConvertToBiblatex()) { + jobs.add(new BiblatexCleanup()); + } + return jobs; + } +} diff --git a/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java index fe61f5b43d9..4fdf0e450a6 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/DoiCleanup.java @@ -1,3 +1,17 @@ +/* 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.logic.cleanup; import java.util.ArrayList; @@ -11,7 +25,7 @@ /** * Formats the DOI (e.g. removes http part) and also moves DOIs from note, url or ee field to the doi field. */ -public class DoiCleanup implements Cleaner { +public class DoiCleanup implements CleanupJob { /** * Fields to check for DOIs. diff --git a/src/main/java/net/sf/jabref/logic/cleanup/FieldFormatterCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/FieldFormatterCleanup.java index e2c8e762b26..7fdd1ba47d9 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/FieldFormatterCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/FieldFormatterCleanup.java @@ -1,3 +1,17 @@ +/* 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.logic.cleanup; import java.util.ArrayList; @@ -17,18 +31,18 @@ /** * Formats a given entry field with the specified formatter. */ -public class FieldFormatterCleanup implements Cleaner { +public class FieldFormatterCleanup implements CleanupJob { private final String field; private final Formatter formatter; - public static Cleaner PAGE_NUMBERS = new FieldFormatterCleanup("pages", BibtexFieldFormatters.PAGE_NUMBERS); - public static Cleaner DATES = new FieldFormatterCleanup("date", BibtexFieldFormatters.DATE); - public static Cleaner MONTH = new FieldFormatterCleanup("month", new MonthFormatter()); - public static Cleaner TITLE_CASE = new FieldFormatterCleanup("title", new CaseKeeper()); - public static Cleaner TITLE_UNITS = new FieldFormatterCleanup("title", new UnitFormatter()); - public static Cleaner TITLE_LATEX = new FieldFormatterCleanup("title", new LatexFormatter()); - public static Cleaner TITLE_HTML = new FieldFormatterCleanup("title", new HTMLConverter()); + public static CleanupJob PAGE_NUMBERS = new FieldFormatterCleanup("pages", BibtexFieldFormatters.PAGE_NUMBERS); + public static CleanupJob DATES = new FieldFormatterCleanup("date", BibtexFieldFormatters.DATE); + public static CleanupJob MONTH = new FieldFormatterCleanup("month", new MonthFormatter()); + public static CleanupJob TITLE_CASE = new FieldFormatterCleanup("title", new CaseKeeper()); + public static CleanupJob TITLE_UNITS = new FieldFormatterCleanup("title", new UnitFormatter()); + public static CleanupJob TITLE_LATEX = new FieldFormatterCleanup("title", new LatexFormatter()); + public static CleanupJob TITLE_HTML = new FieldFormatterCleanup("title", new HTMLConverter()); public FieldFormatterCleanup(String field, Formatter formatter) { diff --git a/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java new file mode 100644 index 00000000000..4c358c3751c --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/cleanup/FileLinksCleanup.java @@ -0,0 +1,49 @@ +/* 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.logic.cleanup; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import net.sf.jabref.Globals; +import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FileField; + +/** + * Fixes the format of the file field. For example, if the file link is empty but the description wrongly contains the path. + */ +public class FileLinksCleanup implements CleanupJob { + + @Override + public List cleanup(BibEntry entry) { + Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + if (!oldValue.isPresent()) { + return new ArrayList<>(); + } + + List fileList = FileField.parse(oldValue.get()); + + // Parsing automatically moves a single description to link, so we just need to write the fileList back again + String newValue = FileField.getStringRepresentation(fileList); + if (!oldValue.get().equals(newValue)) { + entry.setField(Globals.FILE_FIELD, newValue); + FieldChange change = new FieldChange(entry, Globals.FILE_FIELD, oldValue.get(), newValue); + return Collections.singletonList(change); + } + return new ArrayList<>(); + } +} diff --git a/src/main/java/net/sf/jabref/logic/cleanup/FormatterCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/FormatterCleanup.java index 85b4805bbe6..f7ee6103857 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/FormatterCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/FormatterCleanup.java @@ -1,3 +1,17 @@ +/* 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.logic.cleanup; import java.util.ArrayList; @@ -10,7 +24,7 @@ /** * Runs a formatter on every field. */ -public class FormatterCleanup implements Cleaner { +public class FormatterCleanup implements CleanupJob { private final Formatter formatter; diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java new file mode 100644 index 00000000000..a929d4f30a7 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/cleanup/RelativePathsCleanup.java @@ -0,0 +1,67 @@ +/* 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.logic.cleanup; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import net.sf.jabref.Globals; +import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.logic.util.io.FileUtil; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FileField; + +public class RelativePathsCleanup implements CleanupJob { + + private final List paths; + + public RelativePathsCleanup(List paths) { + this.paths = paths; + } + + @Override + public List cleanup(BibEntry entry) { + Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + if (!oldValue.isPresent()) { + return new ArrayList<>(); + } + + List fileList = FileField.parse(oldValue.get()); + List newFileList = new ArrayList<>(); + boolean changed = false; + for (FileField.ParsedFileField flEntry : fileList) { + String oldFileName = flEntry.link; + String newFileName = FileUtil.shortenFileName(new File(oldFileName), paths).toString(); + + FileField.ParsedFileField newFlEntry = flEntry; + if (!oldFileName.equals(newFileName)) { + newFlEntry = new FileField.ParsedFileField(flEntry.description, newFileName, flEntry.fileType); + changed = true; + } + newFileList.add(newFlEntry); + } + if (changed) { + String newValue = FileField.getStringRepresentation(newFileList); + assert (!oldValue.get().equals(newValue)); + entry.setField(Globals.FILE_FIELD, newValue); + FieldChange change = new FieldChange(entry, Globals.FILE_FIELD, oldValue.get(), newValue); + return Collections.singletonList(change); + } + return new ArrayList<>(); + } + +} diff --git a/src/main/java/net/sf/jabref/logic/cleanup/RemoveFieldCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RemoveFieldCleanup.java index 4cd7c1f272c..ac8f62d41ec 100644 --- a/src/main/java/net/sf/jabref/logic/cleanup/RemoveFieldCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RemoveFieldCleanup.java @@ -1,3 +1,17 @@ +/* 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.logic.cleanup; import java.util.ArrayList; @@ -10,7 +24,7 @@ /** * Removes a given field. */ -public class RemoveFieldCleanup implements Cleaner { +public class RemoveFieldCleanup implements CleanupJob { private final String field; diff --git a/src/main/java/net/sf/jabref/gui/actions/RenamePdfCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java similarity index 58% rename from src/main/java/net/sf/jabref/gui/actions/RenamePdfCleanup.java rename to src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java index b6fcc4a0a12..16081f1cc73 100644 --- a/src/main/java/net/sf/jabref/gui/actions/RenamePdfCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/RenamePdfCleanup.java @@ -1,29 +1,39 @@ -package net.sf.jabref.gui.actions; +/* 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.logic.cleanup; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import net.sf.jabref.Globals; -import net.sf.jabref.external.ExternalFileType; -import net.sf.jabref.gui.FileListEntry; -import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.logic.FieldChange; -import net.sf.jabref.logic.cleanup.Cleaner; import net.sf.jabref.logic.util.io.FileUtil; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FileField; import net.sf.jabref.util.Util; -public class RenamePdfCleanup implements Cleaner { +public class RenamePdfCleanup implements CleanupJob { private final List paths; private final BibDatabase database; private final Boolean onlyRelativePaths; private int unsuccessfulRenames; - public RenamePdfCleanup(List paths, Boolean onlyRelativePaths, BibDatabase database) { this.paths = paths; this.database = database; @@ -33,29 +43,27 @@ public RenamePdfCleanup(List paths, Boolean onlyRelativePaths, BibDataba @Override public List cleanup(BibEntry entry) { //Extract the path - if (!entry.hasField(Globals.FILE_FIELD)) { - return new ArrayList<>(); - } - String oldValue = entry.getField(Globals.FILE_FIELD); - FileListTableModel flModel = new FileListTableModel(); - flModel.setContent(oldValue); - if (flModel.getRowCount() == 0) { + Optional oldValue = entry.getFieldOptional(Globals.FILE_FIELD); + if (!oldValue.isPresent()) { return new ArrayList<>(); } - boolean changed = false; - for (int i = 0; i < flModel.getRowCount(); i++) { - String realOldFilename = flModel.getEntry(i).link; + List fileList = FileField.parse(oldValue.get()); + List newFileList = new ArrayList<>(); + boolean changed = false; + for (FileField.ParsedFileField flEntry : fileList) { + String realOldFilename = flEntry.link; if (onlyRelativePaths && (new File(realOldFilename).isAbsolute())) { continue; } - String newFilename = Util.getLinkedFileName(database, entry); + StringBuilder newFilename = new StringBuilder(Util.getLinkedFileName(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).type.getExtension(); + newFilename.append("."); + newFilename.append(FileUtil.getFileExtension(realOldFilename).orElse("pdf")); //get new Filename with path //Create new Path based on old Path and new filename @@ -64,8 +72,8 @@ public List cleanup(BibEntry entry) { // something went wrong. Just skip this entry continue; } - String newPath = expandedOldFile.getParent().concat(System.getProperty("file.separator")) - .concat(newFilename); + String newPath = expandedOldFile.getParent().concat(System.getProperty("file.separator")).concat( + newFilename.toString()); if (new File(newPath).exists()) { // we do not overwrite files @@ -80,33 +88,32 @@ public List cleanup(BibEntry entry) { changed = true; //Change the path for this entry - String description = flModel.getEntry(i).description; - ExternalFileType type = flModel.getEntry(i).type; - flModel.removeEntry(i); + String description = flEntry.description; + String type = flEntry.fileType; // 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; + if (parent == null || paths.contains(parent.getAbsolutePath())) { + newFileEntryFileName = newFilename.toString(); } else { - newFileEntryFileName = parent.toString().concat(System.getProperty("file.separator")) - .concat(newFilename); + newFileEntryFileName = parent.toString().concat(System.getProperty("file.separator")).concat( + newFilename.toString()); } - flModel.addEntry(i, new FileListEntry(description, newFileEntryFileName, type)); + newFileList.add(new FileField.ParsedFileField(description, newFileEntryFileName, type)); } else { unsuccessfulRenames++; } } if (changed) { - String newValue = flModel.getStringRepresentation(); - assert(!oldValue.equals(newValue)); + String newValue = FileField.getStringRepresentation(newFileList); + assert (!oldValue.get().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. - FieldChange change = new FieldChange(entry, Globals.FILE_FIELD, oldValue, newValue); + FieldChange change = new FieldChange(entry, Globals.FILE_FIELD, oldValue.get(), newValue); return Collections.singletonList(change); } diff --git a/src/main/java/net/sf/jabref/gui/actions/UnicodeCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/UnicodeCleanup.java similarity index 51% rename from src/main/java/net/sf/jabref/gui/actions/UnicodeCleanup.java rename to src/main/java/net/sf/jabref/logic/cleanup/UnicodeCleanup.java index 78e26171c51..1652eb94ffb 100644 --- a/src/main/java/net/sf/jabref/gui/actions/UnicodeCleanup.java +++ b/src/main/java/net/sf/jabref/logic/cleanup/UnicodeCleanup.java @@ -1,17 +1,30 @@ -package net.sf.jabref.gui.actions; +/* 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.logic.cleanup; import java.util.ArrayList; import java.util.List; import net.sf.jabref.importer.HTMLConverter; import net.sf.jabref.logic.FieldChange; -import net.sf.jabref.logic.cleanup.Cleaner; import net.sf.jabref.model.entry.BibEntry; /** * Converts Unicode characters to LaTeX code. */ -public class UnicodeCleanup implements Cleaner { +public class UnicodeCleanup implements CleanupJob { @Override public List cleanup(BibEntry entry) { @@ -19,7 +32,7 @@ public List cleanup(BibEntry entry) { final String[] fields = {"title", "author", "abstract"}; for (String field : fields) { if (!entry.hasField(field)) { - break; + continue; } String oldValue = entry.getField(field); final HTMLConverter htmlConverter = new HTMLConverter(); diff --git a/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java b/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java new file mode 100644 index 00000000000..8f1c06fa2b6 --- /dev/null +++ b/src/main/java/net/sf/jabref/logic/cleanup/UpgradePdfPsToFileCleanup.java @@ -0,0 +1,71 @@ +/* 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.logic.cleanup; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import net.sf.jabref.Globals; +import net.sf.jabref.external.ExternalFileTypes; +import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FileField; + +/** + * Collects file links from the given set of fields, and add them to the list contained in the file field. + */ +public class UpgradePdfPsToFileCleanup implements CleanupJob { + + private final List fields; + + public UpgradePdfPsToFileCleanup(List fields) { + this.fields = Objects.requireNonNull(fields); + } + + @Override + public List cleanup(BibEntry entry) { + List changes = new ArrayList<>(); + + // If there are already links in the file field, keep those on top: + String oldFileContent = entry.getField(Globals.FILE_FIELD); + + List fileList = new ArrayList<>(FileField.parse(oldFileContent)); + int oldItemCount = fileList.size(); + for (String field : fields) { + entry.getFieldOptional(field).ifPresent(o -> { + if (o.trim().isEmpty()) { + return; + } + File f = new File(o); + FileField.ParsedFileField flEntry = new FileField.ParsedFileField(f.getName(), o, + ExternalFileTypes.getInstance().getExternalFileTypeNameByExt(field)); + fileList.add(flEntry); + + entry.clearField(field); + changes.add(new FieldChange(entry, field, o, null)); + }); + } + + if (fileList.size() != oldItemCount) { + String newValue = FileField.getStringRepresentation(fileList); + entry.setField(Globals.FILE_FIELD, newValue); + changes.add(new FieldChange(entry, Globals.FILE_FIELD, oldFileContent, newValue)); + } + + return changes; + } +} diff --git a/src/main/java/net/sf/jabref/logic/util/io/FileUtil.java b/src/main/java/net/sf/jabref/logic/util/io/FileUtil.java index 441a93aee85..b8f3b56dfd4 100644 --- a/src/main/java/net/sf/jabref/logic/util/io/FileUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/io/FileUtil.java @@ -272,10 +272,7 @@ public static File expandFilename(String name, String dir) { * @param dirs directories to check. */ public static File shortenFileName(File fileName, List dirs) { - if ((fileName == null) || (fileName.length() == 0)) { - return fileName; - } - if (!fileName.isAbsolute() || (dirs == null)) { + if (fileName == null || !fileName.isAbsolute() || (dirs == null)) { return fileName; } @@ -291,10 +288,7 @@ public static File shortenFileName(File fileName, List dirs) { } private static File shortenFileName(File fileName, String dir) { - if ((fileName == null) || (fileName.length() == 0)) { - return fileName; - } - if (!fileName.isAbsolute() || (dir == null)) { + if (fileName == null || !fileName.isAbsolute() || (dir == null)) { return fileName; } diff --git a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java index a63e848cedd..4aa33625a3b 100644 --- a/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java +++ b/src/main/java/net/sf/jabref/migrations/FileLinksUpgradeWarning.java @@ -15,6 +15,7 @@ */ package net.sf.jabref.migrations; +import java.util.Arrays; import java.util.List; import javax.swing.*; @@ -23,16 +24,18 @@ import net.sf.jabref.gui.BasePanel; import net.sf.jabref.gui.actions.BrowseAction; import net.sf.jabref.gui.entryeditor.EntryEditorTabList; +import net.sf.jabref.gui.undo.UndoableFieldChange; import net.sf.jabref.importer.ParserResult; import net.sf.jabref.importer.PostOpenAction; import net.sf.jabref.gui.undo.NamedCompound; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; +import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.logic.cleanup.UpgradePdfPsToFileCleanup; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.util.Util; /** * This class defines the warning that can be offered when opening a pre-2.3 @@ -184,7 +187,7 @@ private void makeChanges(BasePanel panel, ParserResult pr, boolean upgradePrefs, if (upgradeDatabase) { // Update file links links in the database: - NamedCompound ce = Util.upgradePdfPsToFile(pr.getDatabase(), FileLinksUpgradeWarning.FIELDS_TO_LOOK_FOR); + NamedCompound ce = upgradePdfPsToFile(pr.getDatabase(), FileLinksUpgradeWarning.FIELDS_TO_LOOK_FOR); panel.undoManager.addEdit(ce); panel.markBaseChanged(); } @@ -229,4 +232,27 @@ private boolean showsFileInGenFields() { return found; } + /** + * Collect file links from the given set of fields, and add them to the list contained in the field + * GUIGlobals.FILE_FIELD. + * + * @param database The database to modify. + * @param fields The fields to find links in. + * @return A CompoundEdit specifying the undo operation for the whole operation. + */ + private static NamedCompound upgradePdfPsToFile(BibDatabase database, String[] fields) { + NamedCompound ce = new NamedCompound(Localization.lang("Move external links to 'file' field")); + + UpgradePdfPsToFileCleanup cleanupJob = new UpgradePdfPsToFileCleanup(Arrays.asList(fields)); + for (BibEntry entry : database.getEntryMap().values()) { + List changes = cleanupJob.cleanup(entry); + + for (FieldChange change : changes) { + ce.addEdit(new UndoableFieldChange(change)); + } + } + + ce.end(); + return ce; + } } diff --git a/src/main/java/net/sf/jabref/model/entry/FileField.java b/src/main/java/net/sf/jabref/model/entry/FileField.java index f69d2ad010a..c9d2316e738 100644 --- a/src/main/java/net/sf/jabref/model/entry/FileField.java +++ b/src/main/java/net/sf/jabref/model/entry/FileField.java @@ -188,4 +188,8 @@ public static String getStringRepresentation(List fields) { } return encodeStringArray(array); } + + public static String getStringRepresentation(ParsedFileField field) { + return getStringRepresentation(Collections.singletonList(field)); + } } diff --git a/src/main/java/net/sf/jabref/util/Util.java b/src/main/java/net/sf/jabref/util/Util.java index f0f8aaaf1e3..47f87c6b86e 100644 --- a/src/main/java/net/sf/jabref/util/Util.java +++ b/src/main/java/net/sf/jabref/util/Util.java @@ -48,7 +48,6 @@ import net.sf.jabref.logic.util.strings.UnicodeToReadableCharMap; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.entry.BibEntry; -import net.sf.jabref.model.entry.FileField; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -320,60 +319,6 @@ private static void setAutomaticFields(BibEntry entry, boolean setOwner, String } } - /** - * Collect file links from the given set of fields, and add them to the list contained in the field - * GUIGlobals.FILE_FIELD. - * - * @param database The database to modify. - * @param fields The fields to find links in. - * @return A CompoundEdit specifying the undo operation for the whole operation. - */ - public static NamedCompound upgradePdfPsToFile(BibDatabase database, String[] fields) { - NamedCompound ce = new NamedCompound(Localization.lang("Move external links to 'file' field")); - - for (BibEntry entry : database.getEntryMap().values()) { - upgradePdfPsToFile(entry, fields, ce); - } - - ce.end(); - return ce; - } - - /** - * TODO: Move this to cleanup class. Collect file links from the given set of fields, and add them to the list - * contained in the field GUIGlobals.FILE_FIELD. - *

- * @param entry The entry to modify. - * >>>>>>> origin/master - * @param fields The fields to find links in. - * @return A CompoundEdit specifying the undo operation for the whole operation. - */ - public static void upgradePdfPsToFile(BibEntry entry, String[] fields, NamedCompound ce) { - // If there are already links in the file field, keep those on top: - String oldFileContent = entry.getField(Globals.FILE_FIELD); - List fileList = FileField.parse(oldFileContent); - int oldItemCount = fileList.size(); - for (String field : fields) { - entry.getFieldOptional(field).ifPresent(o -> { - if (o.trim().isEmpty()) { - return; - } - File f = new File(o); - FileField.ParsedFileField flEntry = new FileField.ParsedFileField(f.getName(), o, - ExternalFileTypes.getInstance().getExternalFileTypeNameByExt(field)); - fileList.add(flEntry); - - entry.clearField(field); - ce.addEdit(new UndoableFieldChange(entry, field, o, null)); - }); - } - if (fileList.size() != oldItemCount) { - String newValue = FileField.getStringRepresentation(fileList); - entry.setField(Globals.FILE_FIELD, newValue); - ce.addEdit(new UndoableFieldChange(entry, Globals.FILE_FIELD, oldFileContent, newValue)); - } - } - /** * This method looks up what kind of external binding is used for the given field, and constructs on OpenFileFilter * suitable for browsing for an external file. diff --git a/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java new file mode 100644 index 00000000000..3b8f0bc148d --- /dev/null +++ b/src/test/java/net/sf/jabref/logic/cleanup/CleanupWorkerTest.java @@ -0,0 +1,265 @@ +package net.sf.jabref.logic.cleanup; + +import net.sf.jabref.logic.FieldChange; +import net.sf.jabref.model.entry.BibEntry; +import net.sf.jabref.model.entry.FileField; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; + +public class CleanupWorkerTest { + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + + @SuppressWarnings("unused") + @Test(expected = NullPointerException.class) + public void initWithNullPresetThrowsException() { + new CleanupWorker(null); + } + + @Test(expected = NullPointerException.class) + public void cleanupNullThrowsException() { + CleanupPreset preset = new CleanupPreset(EnumSet.noneOf(CleanupPreset.CleanupStep.class)); + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(null); + } + + @Test + public void cleanupDoesNothingByDefault() throws IOException { + CleanupPreset preset = new CleanupPreset(EnumSet.noneOf(CleanupPreset.CleanupStep.class)); + CleanupWorker worker = new CleanupWorker(preset); + BibEntry entry = new BibEntry(); + entry.setField(BibEntry.KEY_FIELD, "Toot"); + entry.setField("pdf", "aPdfFile"); + entry.setField("some", "1st"); + entry.setField("doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); + entry.setField("month", "01"); + entry.setField("pages", "1-2"); + entry.setField("date", "01/1999"); + entry.setField("pdf", "aPdfFile"); + entry.setField("ps", "aPsFile"); + entry.setField("file", "link::"); + entry.setField("journal", "test"); + entry.setField("title", "hallo units 1 A case AlGaAs and latex $\\alpha$$\\beta$"); + entry.setField("abstract", "Réflexions"); + File tempFile = testFolder.newFile(); + FileField.ParsedFileField fileField = new FileField.ParsedFileField("", tempFile.getAbsolutePath(), ""); + entry.setField("file", FileField.getStringRepresentation(fileField)); + + List changes = worker.cleanup(entry); + Assert.assertEquals(Collections.emptyList(), changes); + } + + @Test + public void upgradeExternalLinksMoveFromPdfToFile() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); + BibEntry entry = new BibEntry(); + entry.setField("pdf", "aPdfFile"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals(null, entry.getField("pdf")); + Assert.assertEquals("aPdfFile:aPdfFile:PDF", entry.getField("file")); + } + + @Test + public void upgradeExternalLinksMoveFromPsToFile() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); + BibEntry entry = new BibEntry(); + entry.setField("ps", "aPsFile"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals(null, entry.getField("pdf")); + Assert.assertEquals("aPsFile:aPsFile:PostScript", entry.getField("file")); + } + + @Test + public void cleanupSupercriptChangesFirstToLatex() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_SUPERSCRIPTS); + BibEntry entry = new BibEntry(); + entry.setField("some", "1st"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("1\\textsuperscript{st}", entry.getField("some")); + } + + @Test + public void cleanupDoiRemovesLeadingHttp() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_DOI); + BibEntry entry = new BibEntry(); + entry.setField("doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("10.1016/0001-8708(80)90035-3", entry.getField("doi")); + } + + @Test + public void cleanupDoiReturnsChanges() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_DOI); + BibEntry entry = new BibEntry(); + entry.setField("doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); + + CleanupWorker worker = new CleanupWorker(preset); + List changes = worker.cleanup(entry); + + FieldChange expectedChange = new FieldChange(entry, "doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3", + "10.1016/0001-8708(80)90035-3"); + Assert.assertEquals(Collections.singletonList(expectedChange), changes); + } + + @Test + public void cleanupMonthChangesNumberToBibtex() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_MONTH); + BibEntry entry = new BibEntry(); + entry.setField("month", "01"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("#jan#", entry.getField("month")); + } + + @Test + public void cleanupPageNumbersConvertsSingleDashToDouble() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_PAGE_NUMBERS); + BibEntry entry = new BibEntry(); + entry.setField("pages", "1-2"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("1--2", entry.getField("pages")); + } + + @Test + public void cleanupDatesConvertsToCorrectFormat() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_DATE); + BibEntry entry = new BibEntry(); + entry.setField("date", "01/1999"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("1999-01", entry.getField("date")); + } + + @Test + public void cleanupFixFileLinksMovesSingleDescriptionToLink() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.FIX_FILE_LINKS); + BibEntry entry = new BibEntry(); + entry.setField("file", "link::"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals(":link:", entry.getField("file")); + } + + @Test + public void cleanupRelativePathsConvertAbsoluteToRelativePath() throws IOException { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.MAKE_PATHS_RELATIVE); + + File tempFile = testFolder.newFile(); + BibEntry entry = new BibEntry(); + FileField.ParsedFileField fileField = new FileField.ParsedFileField("", tempFile.getAbsolutePath(), ""); + entry.setField("file", FileField.getStringRepresentation(fileField)); + + CleanupWorker worker = new CleanupWorker(preset, + Collections.singletonList(testFolder.getRoot().getAbsolutePath())); + worker.cleanup(entry); + FileField.ParsedFileField newFileField = new FileField.ParsedFileField("", tempFile.getName(), ""); + Assert.assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); + } + + @Test + public void cleanupRenamePdfRenamesRelativeFile() throws IOException { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.RENAME_PDF); + + File tempFile = testFolder.newFile(); + BibEntry entry = new BibEntry(); + entry.setField(BibEntry.KEY_FIELD, "Toot"); + FileField.ParsedFileField fileField = new FileField.ParsedFileField("", tempFile.getAbsolutePath(), ""); + entry.setField("file", FileField.getStringRepresentation(fileField)); + + CleanupWorker worker = new CleanupWorker(preset, + Collections.singletonList(testFolder.getRoot().getAbsolutePath())); + worker.cleanup(entry); + FileField.ParsedFileField newFileField = new FileField.ParsedFileField("", "Toot.tmp", ""); + Assert.assertEquals(FileField.getStringRepresentation(newFileField), entry.getField("file")); + } + + @Test + public void cleanupHtmlStripsHtmlTag() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CONVERT_HTML_TO_LATEX); + BibEntry entry = new BibEntry(); + entry.setField("title", "hallo"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("hallo", entry.getField("title")); + } + + @Test + public void cleanupUnitsConvertsOneAmpereToLatex() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CONVERT_UNITS); + BibEntry entry = new BibEntry(); + entry.setField("title", "1 A"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("1~{A}", entry.getField("title")); + } + + @Test + public void cleanupCasesAddsBracketAroundAluminiumGalliumArsenid() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CONVERT_CASE); + BibEntry entry = new BibEntry(); + entry.setField("title", "AlGaAs"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("{AlGaAs}", entry.getField("title")); + } + + @Test + public void cleanupLatexMergesTwoLatexMathEnvironments() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CONVERT_LATEX); + BibEntry entry = new BibEntry(); + entry.setField("title", "$\\alpha$$\\beta$"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("$\\alpha\\beta$", entry.getField("title")); + } + + @Test + public void cleanupUnicodeConvertsAcuteToLatex() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CONVERT_UNICODE_TO_LATEX); + BibEntry entry = new BibEntry(); + entry.setField("abstract", "Réflexions"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals("R{\\'{e}}flexions", entry.getField("abstract")); + } + + @Test + public void convertToBiblatexMovesJournalToJournalTitle() { + CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX); + BibEntry entry = new BibEntry(); + entry.setField("journal", "test"); + + CleanupWorker worker = new CleanupWorker(preset); + worker.cleanup(entry); + Assert.assertEquals(null, entry.getField("journal")); + Assert.assertEquals("test", entry.getField("journaltitle")); + } +}